When I'm switching the compiler version from gcc 4.6 to gcc 4.8 I get the following error
error: call of overloaded 'isnan(double)' is ambiguous.
This is because in c++11 there are differend function declarations:
C: int isnan(double)
C++11: bool isnan(double)
from cpluplus:
In C, this is implemented as a macro that returns an int value. The type of x shall be float, double or long double.
In C++, it is implemented with function overloads for each floating-point type, each returning a bool value.
How can I fix this?
Although you can mitigate this problem by not saying using namespace std; everywhere, you can avoid it by being explicit about using std::isnan:
#include <cmath>
#include <iostream>
int main()
{
double x = ....;
std::cout << std::boolalpha;
std::cout << std::isnan(x) << std::endl;
}
In C++11 there should not be ambiguity between the C and C++ isnan function. It works as expected, even with using namespace std.
Please check that you are not doing both #include <math.h> and #include <cmath>. Only include cmath.
Alternatively, perhaps you somewhere have in your project a user-defined isnan(double) function, or some header includes "math.h".
Also please note, that if one wants to write generic code, it is incorrect to use the 'std::' prefix on the math functions as it breaks the argument dependent lookup (ADL). (Because the C++ standard does not allow injecting functions in the std:: namespace)
The correct use for isnan in generic code is using std::isnan; then use just isnan on the variables. Otherwise your code with user defined floating point types such as for arbitrary precision, automatic differentiation and such wont work. The root of this inconsistency is that the built in types such as double do not reside in the namespace std but the functions that operate on them do.
Related
#include <iostream>
#include <cmath>
/* Intentionally incorrect abs() which seems to override std::abs() */
int abs(int a) {
return a > 0? -a : a;
}
int main() {
int a = abs(-5);
int b = std::abs(-5);
std::cout<< a << std::endl << b << std::endl;
return 0;
}
I expected that the output will be -5and 5, but the output is the -5 and -5.
I wonder why this case will happen?
Does it have anything to do with the use of std or what?
The language specification allows implementations to implement <cmath> by declaring (and defining) the standard functions in global namespace and then bringing them into namespace std by means of using-declarations. It is unspecified whether this approach is used
20.5.1.2 Headers
4 [...] In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (6.3.6) of the namespace std. It is unspecified whether these names (including any overloads
added in Clauses 21 through 33 and Annex D) are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (10.3.3).
Apparently, you are dealing with one of implementations that decided to follow this approach (e.g. GCC). I.e. your implementation provides ::abs, while std::abs simply "refers" to ::abs.
One question that remains in this case is why in addition to the standard ::abs you were able to declare your own ::abs, i.e. why there's no multiple definition error. This might be caused by another feature provided by some implementations (e.g. GCC): they declare standard functions as so called weak symbols, thus allowing you to "replace" them with your own definitions.
These two factors together create the effect you observe: weak-symbol replacement of ::abs also results in replacement of std::abs. How well this agrees with the language standard is a different story... In any case, don't rely on this behavior - it is not guaranteed by the language.
In GCC this behavior can be reproduced by the following minimalistic example. One source file
#include <iostream>
void foo() __attribute__((weak));
void foo() { std::cout << "Hello!" << std::endl; }
Another source file
#include <iostream>
void foo();
namespace N { using ::foo; }
void foo() { std::cout << "Goodbye!" << std::endl; }
int main()
{
foo();
N::foo();
}
In this case you will also observe that the new definition of ::foo ("Goodbye!") in the second source file also affects the behavior of N::foo. Both calls will output "Goodbye!". And if you remove the definition of ::foo from the second source file, both calls will dispatch to the "original" definition of ::foo and output "Hello!".
The permission given by the above 20.5.1.2/4 is there to simplify implementation of <cmath>. Implementations are allowed to simply include C-style <math.h>, then redeclare the functions in std and add some C++-specific additions and tweaks. If the above explanation properly describes the inner mechanics of the issue, then a major part of it depends on replaceability of weak symbols for C-style versions of the functions.
Note that if we simply globally replace int with double in the above program, the code (under GCC) will behave "as expected" - it will output -5 5. This happens because C standard library does not have abs(double) function. By declaring our own abs(double), we do not replace anything.
But if after switching from int with double we also switch from abs to fabs, the original weird behavior will reappear in its full glory (output -5 -5).
This is consistent with the above explanation.
Your code causes undefined behaviour.
C++17 [extern.names]/4:
Each function signature from the C standard library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
So you cannot make a function with the same prototype as the Standard C library function int abs(int);. Regardless of which headers you actually include or whether those headers also put C library names into the global namespace.
However, it would be allowed to overload abs if you provide different parameter types.
various programs in C++ are written without using scope resolution operator in this way:
#include <iostream>
#include <string>
int main()
{
std::string name = "My Name";
std::cout << name << std::endl;
return 0;
}
and I have also seen using "using" keyword:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name = "My Name";
cout << name << endl;
return 0;
}
which one is better for efficiency reasons?
Assuming the same names end up being found the efficiency is the same: independent of how the function name is spelled the same function is being called. The main difference is how names are being located. Using full qualification prevents, e.g., argument-dependent look-up and is, thus, easier to understand.
Of course, when you actually do have a customization point you'd want to use an unqualified call for argument-dependent look-up to kick in. If there is no need for a default implementation for the customization point there is no need to have a using declaration or even a using directive. Incorrect use of customization points can have a negative performance impact. For example, when using swap() you do not want use the name qualified:
template <typename T>
void some_function(T& v1, T& v2) {
std::swap(v1, v2); // <--- this is bad! It uses the default implementation
using std::swap; // make a default implementation visible
swap(v1, v2); // <--- this is better: if it exists uses T's swap()
}
If T has a customized swap() it is likely more efficient than std::swap() which may cause copies of the values v1 and v2. With move-enabled types T the difference isn't as bad but it could still be substantial. Of course, the issue here isn't the use of qualification or no qualification but rather the fact that the two ways to call a function may result in different functions being found depending on whether swap() is overloaded for T.
BTW, if you are interested in efficiency, do not use std::endl!
The two programs should produce identical executable code. In C++ name lookup happens at compile-time, not run-time, so the compiler finds the name during compilation and then nothing changes later. There is no run-time evaluation, so the syntax used to find a given name can't affect the program's efficiency.
As Dietmar says, the choice of syntax might cause a different name to be found, which could alter the behaviour, but assuming the same name is found there can be no difference in efficiency.
Consider following code:
#include <iostream>
#include <math.h>
double log(double) { return 42; }
int main() {
std::cout << log(1) << std::endl;
}
While build debug version all used compilers (msvc,gcc,clang) prints 42.
But when i try build (and run) in release mode i got:
compilation error in msvc: error C2169: 'log' : intrinsic function, cannot be defined;
prints 42 for gcc;
prints 0 for clang.
Why release/debug results are different for same compiler?
Why got different results for different compilers in release mode?
You are defining a function that is already declared in <math.h> with external linkage.
C11 standard, §7.12.6.7:
#include <math.h>
double log(double x);
§7.1.2:
Any declaration of a library function shall have external linkage.
[extern.names]/3:
Each name from the Standard C library declared with external linkage
is reserved to the implementation for use as a name with extern "C"
linkage, both in namespace std and in the global namespace.
According to [reserved.names]/2 the behavior is undefined; The implementation can thus do what it wants, including the issuance of nonsensical error messages.
So according to the standard (17.6.1.2.4):
In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).
It's unspecified whether or not the log() in math.h (really cmath) is in namespace std or not. If it is (like it is for libstdc++ for gcc), then calling log(1) quite simply calls your function because the other one is named std::log(). But for clang, apparently it puts it in the global namespace. Since there is a
template <typename T> double log(T x);
That will be preferred to yours since you're passing an int, so on clang it will call that one. (I can't check this right now since I can't access coliru and don't have clang installed, but this is a best guess).
I was playing with ptrdiff_t and reading the C++11 standard when I came across this "issue". First, the facts:
The type ptrdiff_t (just an example) is pulled from the Standard C library header <stddef.h> into <cstddef> (§18.2/2). Section 17.6.1.2 tells us that declarations pulled from the C standard library will be within the std namespace:
In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is
unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).
As it also says, the declarations may have been declared in global namespace first and then injected into std. So it would make sense, for my implementation, that the following compiles just fine:
#include <cstddef>
int main(int argc, const char* argv[])
{
std::ptrdiff_t x;
ptrdiff_t y;
return 0;
}
My implementation (gcc 4.6.3) must have declared ptrdiff_t in the global namespace and then injected it into std. However, if I compile the following code, I get an error (notice the <iostream> include):
#include <iostream>
int main(int argc, const char* argv[])
{
std::ptrdiff_t x;
ptrdiff_t y;
return 0;
}
main.cpp: In function ‘int main(int, const char**)’:
main.cpp:6:3: error: ‘ptrdiff_t’ was not declared in this scope
main.cpp:6:3: note: suggested alternatives:
/usr/include/c++/4.6/i686-linux-gnu/./bits/c++config.h:156:28: note: ‘std::ptrdiff_t’
So, since std::ptrdiff_t is available, <iostream> must be including <cstddef> in some way (although it's not required to). But why is the global version not also available as it
was before? Can I not expect this injection to be consistent even when it's actually the same header? This seems like odd behaviour. Whether the injection occurs may be unspecified, but it should at least be either one way or the other, not both, right?
Do not rely on one header including another, if you want something declared/defined in a specific header then you must include it.
For the example you gave, with g++ there are actually two definitions of ptrdiff_t (and size_t for that matter). The first, in namespace std, that comes from <bits/c++config.h>. And the one in the global namespace from <stddef.h> (and so <cstddef>).
The problem is that you did not using the correct header. You should do
#include <cstddef>
instead. However you use
#include<iostream>
And that has a definition of "std::ptrdiff_t" in it indirectly. However, the global "::ptrdiff_t" is not defined in "iostream" and "iostream" did not include "cstddef" as you thought. Instead, "iostream" does include "bits/c++config.h". The actual "std::ptrdiff_t" is defined in that file.
If you look at the content of the file "cstddef" you will find that is is only two "useful" lines there
BTW, the above discussion is for GCC 4.6 and GCC 4.7. For GCC 4.4, "iostream" indrectly include "cstddef" therefore ptrdiff_t will be available in both namespaces (std and global).
#include
#include
The latter line brings in the global "::ptrdiff_t" and the former defines the std namespace one.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
unresolved overloaded function type c++
Consider the code snippet below:
#include <algorithm>
#include <cctype>
#include <string>
using namespace std;
void test(){
std::string str = "Hello World!";
std::transform(str.begin(), str.end(), str.begin(), tolower);
}
There is an error about tolower when compiling with G++: unresolved overloaded function.
If using namespace std; is removed, the code works fine.
Then, my questions are:
What is the relationship between namespace std with C functions?
What is the difference between #include<ctype.h> and #include<cctype>? Although both of them don't work in the example above.
Why std::tolower also doesn't work? What's the difference between std::tolower and tolower?
There is no relationship between namespace std and C functions. But
your code isn't C, it's C++, so you also have to consider C++ functions.
Like std::tolower, for example, in <locale>. Your problem is due to
a concurrence of things:
One of the headers you include includes <locale>. C++ headers are
allowed to include other C++ headers, and which header includes which
other header may vary from one implementation to the other, so the
code you've written might compile with one compiler, and not with
another.
You're trying to pass the function as a pointer to function argument,
to a function template where the argument is a template type
parameter. Simply put, in order to do overload resolution on
tolower here, the compiler must match it to the type of the
argument, and in order to know the type of the argument, the compiler
must do template type deduction based on the exact type of the
function, which it can only know once it has done overload resolution.
If you want the function in <ctype.h> (which you don't, since it would
result in undefined behavior), you can get it either by including
<ctype.h> (which guarantees that it is present in the global
namespace) and using ::tolower, or by explicitly specifying the
overload you want, e.g. static_cast<int (*)(int)>( tolower ) (In this
particular case, static_cast doesn't mean type conversion, but
explicit overload resolution.)
In practice, of course, you don't do this sort of thing. If you're
doing any text processing at all, you'll define all of the necessary
functions as functional object types, which avoid undefined behavior by
either converting the input to unsigned char:
struct ToLower
{
char operator()( char ch ) const
{
return ::tolower( static_cast<unsigned char>( ch ) );
}
};
or by using the functions in <locale> which do work with char:
class ToLower
{
std::locale myLocale; // necessary to guarantee the lifetime of the facet.
std::ctype const* myCType;
public:
ToLower( std::locale const& loc = std::locale() )
; myLocal( loc )
, myCType( &std::use_facet<std::ctype>( loc ) )
{
}
bool operator()( char ch ) const
{
return myCType->tolower( ch );
}
};
Finally, WRT your second question: the difference depends on the version
of C++ you're using and the compiler. Globally, however: <ctype.h>
will introduce the functions into the global namespace; <cctype> will
introduce them into the namespace std::, and maybe (or maybe not) into
the global namespace. (And your third question has already been
answered above: std::tolower refers to a set of overloaded functions
defined in <locale> and <cctype>; ::tolower refers to a single
function defined in <ctype.h>, and just tolower is the equivalent of
::tolower, unless you've done using namespace std, in which case,
it will refer to the overload set of all of the functions mentionned
above.
You can use the namespace operator to use the C version of tolower like this:
::tolower(); // nothing before '::' means look in the global namespaece.
This will force the compiler to look for a function that is not inside a specific namespace, which is the case for all C-based API.
As for why std::tolowerdoesn't work, I have no idea. The example of cpp reference doesn't use std::transform, this might be the reason.