Reputation: 621
Why the first code snippet works fine, but the second causes an ambiguous call error ? Why cannot the compiler resolve the function overload in the second case ?
Snippet 1:
int main() {
int x = 1234;
std::cout << x;
}
Snippet 2:
int main() {
int x = 1234;
operator<<(std::cout, x);
}
The compiler error when compiling the snippet 2:
more than one instance of "operator<<" matches the argument list
std::operator <<': ambiguous call to overloaded function
Upvotes: 2
Views: 173
Reputation: 19757
You are trying to call a member function (of std::cout
) as if it were a free function: http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt
The ambiguity probably comes from multple matches that all involve some sort of conversions, none of which is preferable. The compiler error probably gives you some horrendous impossible-to-read list of possible matches, all of which seem irrelevant?
For operators, call them as operators, not as functions! There are good reasons to define operators as members, and good reasons to define them as free functions. You shouldn't need to care which is used in any particular case.
If I want to create my own type that supports +
, I may have good technical reasons to choose one approach over the other, and even change my mind in a future version of the library. Should you care which I choose?
Note that operator<<
is a member function for built-in types (i.e. the various flavours of int
s), but is a non-member function for other types, for example char const*
or std::string
.
Upvotes: 4
Reputation: 5260
From here:
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
char ch );
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
signed char ch );
The call will be ambiguous if overload resolution cannot select a match to the call that is uniquely better than such undifferentiable functions. For x
(int), both char
version and signed char
version are fit, so it will be ambiguous. One more example:
#include <iostream>
void foo(char a)
{
}
void foo(signed char b)
{
}
int main() {
foo(1);
}
prog.cc: In function 'int main()': prog.cc:11:10: error: call of overloaded 'foo(int)' is ambiguous foo(1);
But this code works fine operator<<(std::cout, "hello");
Because
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& const char* s );
is the only choice for operator<<(std::cout, "hello");
. One more example:
const char* z = "char*"; // OK
const signed char* x = "signed char*"; // invalid conversion from ‘const char*’ to ‘const signed char*’
const unsigned char y = "unsigned char*"; // invalid conversion from ‘const char*’ to ‘unsigned char’
Upvotes: 0
Reputation: 2999
The operator is a nonstatic member function, so you could use from : how to call an operator as function in C++
#include <iostream>
int main() {
int x = 1234;
std::cout.operator<<(x);
}
Upvotes: 1
Reputation: 409136
Because there is no global (or non-member) operator<<
overloaded function for integers. It's a member of the output stream:
std::cout.operator<<(x);
A good compiler should have shown you the possible alternatives for an ambiguous call, which should have told you this.
Upvotes: 4