I redefined some maths functions (so that they're faster -ie: less accurate-, or use templates). I put these functions in a namespace and they work just fine.
It happens often, though, that I forget to call functions from my namespace (ie: I forget to write mymath::cos
or using mymath::cos;
when I want to call cos
), and it's pretty tough to find out where I forgot it (until now I found it out only by profiling).
Given that
- I only include standard
math.h
orcmath
headers within my math header, and that - I need to include standard math headers (because some of my functions are just wrapp开发者_如何学Pythoners for standard one, and I want them to be inline or they're templated),
is there a portable way to hide standard math function so that a compile error is reported, if global namespace (ie: without a namespace) math functions are used?
A solution could be putting an using namespace mymath;
at the bottom of my math header file, but this solution doesn't seem that great: it breaks the whole purpose of namespaces; I'd prefer having to explicity say whether to use a function from mymath
or from std
so that I am forced to choose between a fester or a more accurate function without the risk of forgetting about it.
EDIT:
Many answers say that if I use cos
from global namespace (without using std
nor mymath
), and include cmath
(and not math.h
), compilation should fail.
I don't know what the standard says about it, but:
#include <cmath>
int main( ) {
cos( M_PI );
return 0;
}
compiles fine with GNU GCC (g++
) 4.5.1 (and older versions).
Put this in a header file, and #include it everywhere:
namespace DontUseMe {
double cos (double) ;
// ...etc.
}
using namespace DontUseMe ;
If you only include cmath
and not math.h
, all functions from that header should be in the std:: namespace. Just never use using namespace std;
and you'll be fine. (cmath
is just math.h
with all things in a namespace)
Do you need to include the math.h and cmath headers directly in your header file? If you do need to, try including the header like this:
namespace arbitrary_name
{
#include <math.h>
}
This will contain all of the math.h definitions inside a new namespace, so you won't accidentally use them elsewhere.
This is not ideal solution. Perhaps there is a better way to do this using anonymous namespaces, but the solution isn't clear to me.
Unfortunately the most robust solution will be to not use the same function names as the standard library. Luckily the standard function names are terse and heavily abbreviated so names such as cosine()
, sine()
, exponent()
, arctan()
would be unique (and arguably better) without having to adorn the name with clumsy prefixes.
Alternatively you might keep the same names but capitalise them: Sin()
, Cos()
, Exp()
etc.
How about this idea: after including < math.h>, use define as follows:
#define sin blahblahblah (just to generate an error)
#define cos blahblahblah (just to generate an error)
What happens is that every sin will be replaced by blahblahblah, which will cause an error. But what will happen is that mymath::sin will be replaced by mymath::blahblahblah (because #define works literally), so it will also generate an error. In this case, if you want to make the task easier for you just temporarily define the function blahblahblah in mymath to avoid showing error for mymath::sin, then compile, and fix all those errors.
However, I would recommend just making "Find in Files" and going through all the functions, and I am sure it will not talk you more than an hour for a very large scale project.
Hope that helps.
Regards,
Rafid
Write some wrapper functions in a separate file.
#include <math.h>
namespace my_wrapper
{
float sin(float n)
{
return std::sin(float n);
}
};
Or something like that. And then only use those in your other files and don't even include or in the other soure files. Yes it's a small pain to write forwarding functions for them all but it's just a one off job and there aren't that many...
With a modern compiler that does link time code generation and can inline across object files this shouldn't be inefficient...
Clifford's my favorite answer so far, but there is another alternative you might envisage: modify the standard headers for this project (only).
There should be an option with your compiler of choice to indicate where the standard library lies, therefore you can duplicate the STL in your project, and modify the files so that the offending names are no longer injected in the global namespace.
It is hackish, but that's the only way I can think of, short of checking the code with a script for any occurrence of cos
/ sin
that is not qualified (ie immediately preceded by ::
).
精彩评论