I already asked a question about this before but with reference to the following code again
#include <iostream> using std::cout; using std::endl; #include <dlfcn.h> int rand() throw() { // get the original rand() function static auto original_rand = (decltype(&rand)) dlsym(RTLD_NEXT, "rand"); cout << "Call made to rand()" << endl; return original_rand(); }
Why does compiling this result in the following error
error: exception specification in declaration does not match previous declaration
Why would this happen? How does the linker know that this is just another rand() function I have declared myself but rather an existing version of rand()
?
Advertisement
Answer
One of your header files (<iostream>
in my case) silently includes <stdlib.h>
, which contains the rand()
function. The latter does not have any exception specification. In your code you try to overload rand()
, but the signature is the same as the one from <stdlib.h>
except the exception specifier (which is not part of the function type, so cannot overload on it alone), hence you get a compile-time error (not a linker error, as you mentioned in the question).
If you wonder why the function rand()
silently included is also visible in the global namespace (not visible only as std::rand
as you may expect), that’s because often the C library functions are imported into the standard C++ header files via a direct
// <new_cpp_header> #include <old_c_header.h>
followed by
namespace std { using old_function_from_old_c_header; }
so the function ends up in both global namespace as well as in namespace std;
. This is not a very good practice IMO, but that’s how most compilers do it nowadays.
For example, the <cstdio>
file has:
// <cstdio> #include <stdio.h> namespace std { using printf; // ... }
so both printf
and std::printf
are visible, even though you include only <cstdio>
(and not <stdio.h>
).