Explicit operator<< selects 'wrong' overload - c++

I'm playing around with variadic templates, and wrote this, based on this answer :
template <size_t... I>
void print(seq<I...>)
{
decltype(std::cout) * dummy[sizeof...(I)] = { &(std::cout << I << ' ')... };
}
Because std::cout::operator<< has a return type, it can be stored, so there's no need for the ( ,0) comma trick.
Now, to shut up the "unused variable 'dummy'" warning, and to print a newline, I tried the following statements, but they didn't do what I wanted:
dummy[0]->operator <<('\n'); // prints 10
(apparently called operator<<(int) instead of operator<<(char)
dummy[0]->operator <<("\n"); // prints a pointer
(apparently called operator<<(const void*) instead of operator<<(const char*)
In the end, I had to write
*dummy[0] << '\n'; // prints a newline as desired
My question is, why did the "wrong" overloads get chosen?

The "wrong" overloads are chosen because only some overloads are members of std::ostream class. The overloads for char and const char* are not members of std::ostream, but free functions, so, in
*dummy[0] << '\n';
argument-dependent lookup will find operator<<(std::ostream&, char), but in
dummy[0]->operator <<('\n');
only member functions will be considered, resulting in std::ostream::operator<<(int) being called.

Related

Function argument binding rules for passing an array by reference vs passing pointer

To prevent any confusion, I very much understand the difference between arrays and pointers, the concept of decay-to-pointer, and the concept of passing an array by reference in C++, etc.
My question here is specifically about the rules used by the compiler to select a function from a set of function overload candidates, when one overload takes an array reference, and the other overload takes a pointer.
For example, suppose we have:
template <class T, std::size_t N>
void foo(const T (&arr)[N])
{
std::cout << "Array-reference overload!" << std::endl;
}
template <class T>
void foo(const T* ptr)
{
std::cout << "Pointer overload!" << std::endl;
}
If we attempt to invoke function template foo() as follows:
const char arr[2] = "A";
foo(arr);
... then my expectation would be that the first overload, the one that takes an array reference, would be selected by the compiler.
However, using GCC 4.9.2, if I compile the above code, I get an error:
test.cpp:28:9: error: call of overloaded ‘foo(const char [2])’ is ambiguous
It's unclear to me why both overloads are considered equally good candidates by the compiler here, since the first overload matches the type exactly, whereas the second overload requires an extra decay-to-pointer step.
Now, I am able to get the above overload working by explicitly using type_traits as follows:
template <class T, std::size_t N>
void foo(const T (&arr)[N])
{
std::cout << "Array-reference overload!" << std::endl;
}
template <class T>
void foo(T ptr, typename std::enable_if<std::is_pointer<T>::value>::type* = 0)
{
std::cout << "Pointer overload!" << std::endl;
}
In this case, the program compiles and the overload that takes an array reference is selected. However, I don't understand why this solution should be necessary. I'd like to understand why the compiler considers a function that requires decay-to-pointer an equally likely overload candidate as the array reference, when the argument passed is very much an array.
the first overload matches the type exactly, whereas the second overload requires an extra decay-to-pointer step.
Because when checking the ranking of implicit conversion sequences in overload resolution, the array-to-pointer conversion is considered as an exact match, thus the 2nd overload has the same rank with the 1st one.
From the standard, $16.3.3.1.1 Standard conversion sequences [over.ics.scs] Table 13 — Conversions
Conversion Category Rank Subclause
No conversions required Identity Exact Match
... ...
Array-to-pointer conversion Lvalue Transformation Exact Match [conv.array]
... ...
It's worth noting that the rank of "No conversions required" (i.e. the case for the 1st overload) is "Exact Match" too.

C++ stringstream inline

I would like to use std::stringstream to create formatted strings, but use the class inline so I don't have stringstream local variables flying around. What I mean is this:
#include <iostream>
#include <ostream>
#include <string>
#include <sstream>
int main(int argc, char* argv[])
{
std::string test = ((std::ostringstream&)
(std::ostringstream("") << "This is a test: " << 50.1 << "abc")
).str();
std::cout << test << std::endl;
return 0;
}
This compiles fine in GCC, however the output is the following:
"0x401d0a50.1abc"
So it seems that stringstream treats the first string as a pointer and outputs the address. Subsequent operator<<'s work fine.
How do I fix this?
Thanks!
The reason is that the << operator is a member for void const*, but a free function taking an std::ostream& as the left hand argument for char const*. Your std::ostringstream( "" ) is a temporary: you can call member functions (even non-const member functions) on it, but a temporary cannot be used to initialize the non-const reference of the global function.
EDIT:
Two points: first, as has been pointed out, g++ does do what you
want if you specify -std=c++11. As T.C. points out, this is
specified in §27.7.3.9, which provides a template overload for
all << with an rvalue reference for the std::istream
parameter.
And second, the classic work around is
to start the expression std::ostringstream( "" ).flush() <<.... flush is a member function (and so can be called on
a temporary) which returns an std::ostream& (so everything
else chains nicely); it also does nothing on
a std::ostringstream.
Found it. The C++11 standard special-cases rvalue streams with an extra template operator<< overload. §27.7.3.9 of the standard:
Rvalue stream insertion [ostream.rvalue]
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
Effects: os << x
Returns: os
It's obviously a better match than the member operator<< that takes a const void * and hence is selected by overload resolution in C++11 mode. In C++98 mode this overload doesn't exist (since there are no rvalue references) and the only viable overload is the member operator<< (since, as James Kanze explains in his answer, the temporary can't bind to the non-const lvalue reference in the free operator<< overload that takes a const char *).

Template and function Overloading

To study the Overloading of Function Templates, I have wrote two functions:
template <typename T>
void pe16_61_compare(const T&, const T&) {
cout <<"template pe16_61_compare(T, T) called" << endl;
}
// plain functions to handle C-style character strings
void pe16_61_compare(const char*, const char*) {
cout <<"normal func pe16_61_compare(...) called" << endl;;
}
and then I have defined some variables and called the function: pe16_61_compare
const char const_arr1[] = "world", const_arr2[] = "hi";
char ch_arr1[] = "world";
// first call
pe16_61_compare(ch_arr1, const_arr1);
// second call
pe16_61_compare(const_arr1, const_arr2);
the output result is:
template pe16_61_compare(T, T) called
normal func pe16_61_compare(...) called
What confuse me is that the first call invoke the template function. For me, for the first call, both two pe16_61_compare function are viable functions and the have the same rank of conversion (non-const to const and array to pointer), and it is said in this case, the template function should be removed from the set of viable functions.
Could any one tell me why?
Thank you for considering my question!
For the first call, T = char[6] is a better match than the conversion to char const *, so the template wins.
For the second call, no single template parameter can work for arrays, so the non-template overload is the only matching one.
If you say,
pe16_61_compare(static_cast<char const *>(const_arr_1),
static_cast<char const *>(const_arr_2));
then both the template instance and the ordinary function are viable and have the same signature, but as a tie breaker the non-template function wins (i.e. this isn't ambiguous).

How cout distinguishes basic types?

Since my shifting from C to C++ I have a question on STL's formatting output. How ostreams tell one basic type from another?
In C with its printf and formatting strings it was pretty straightforward, but in C++ ostreams somehow distinguish basic types automatically. It puzzles me.
For example, in the following code,
int i;
float f;
std::cout << i << std::endl;
std::cout << f << std::endl;
how cout "knows" that i is an int and f is a float?
The compiler converts the operators to function calls. So that
std::cout << i
becomes
operator<<(std::cout, i)
Somewhere buried deep in the bowels of the standard library headers there are function declarations (functionally equivalent to):
std::ostream& operator<<(std::ostream& o, int i);
std::ostream& operator<<(std::ostream& o, double d);
That is, operator<< is overloaded. When the function call is made, the compiler chooses the function overload which is the best match to the arguments passed in.
In the case of std::cout << i, the int overload is chosen. In the case of std::cout<<d, the double overload is chosen.
You can see function overloading in action fairly simply with a contrived example:
#include <stdio.h>
void print(int i) {printf("%d\n", i);}
void print(double d) {printf("%f\n", d);}
int main()
{
int j=5;
double f=7.7;
print(j);
print(f);
}
Producing the output:
5
7.700000
Try it for yourself: http://ideone.com/grlZl.
Edit: As Jesse Good points out, the functions in question are member functions. So really we have:
std::cout << i
becomes
std::cout.operator<<(i)
And in the headers there are declarations (equivalent to):
class ostream {
ostream& operator<<(int i);
ostream& operator<<(double d);
...
};
The same basic idea holds, however.
There are operator<< overloads for each type (int, float etc).
The compiler will then choose the correct one at compile time.
In general, the operator<< have the form std::ostream& operator<<(std::ostream& stream, int number ), where the function is a global function defined in the std namespace. You can overwrite the definition of this function by declaring it in your own namespace (this is done via Argument Dependent Lookup).
The fact the function returns a reference to the stream, means you can string them together. Just remember, whenever you see operator<<, it really is just a function call.
If you want to have a look, and you're using VS, open
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\ostream.
There you'll find all the definitions if you're curious.
Overload resolution on the second argument to operator<<
Function overloading is a form of compile-time polymorphism. A simple example:
void times_two(int& x) { x *= 2; }
void times_two(double& x) { x *= 2; }
int i = 2;
double d = 2.5;
times_two(i); // i now 4
times_two(d); // d now 5.0
In the case of std::ostreams such as std::cout, the operator<<() functions overload in a similar way. From the Standard Library shipped with GCC 3.4.4:
__ostream_type&
operator<<(int __n);
__ostream_type&
operator<<(double __f);
It's an overloaded ostream operator <<. In c++ you can overload a function name based on it's parameters. This is basically what's happening here. http://www.cplusplus.com/reference/iostream/ostream/operator%3C%3C/

C++ overloading

The following code is giving me a compilation error. Can anyone please tell me why?
class mytype {
public:
int value;
mytype(int a) {
value = a;
}
friend ostream& operator<<(ostream& stream, const mytype& a) {
stream << a.value;//works
return stream;
}
friend ostringstream& operator<<(ostringstream& stream, const mytype& a) {
stream << (a.value);//compilation error
return stream;
}
};
Error:
error C2027: use of undefined type
'std::basic_ostringstream<_Elem,_Traits,_Alloc>'
Upon fixing that:
error C2666: 'operator <<' : 18 overloads have similar conversions
Final fix:
Declare constructor as explicit. Works on MSVC then.
I wonder why.
error C2027: use of undefined type 'std::basic_ostringstream<_Elem,_Traits,_Alloc>'
You need #include <sstream> to get the [i/o]stringstream classes.
About the other errors
The problem with an overload of the form
ostringstream& operator<<(ostringstream& stream, const mytype& a)
is that it matches an ostringstream exactly. Why is it a bad thing to have a more exact overload? From the standard, §13.3.3/1-2:
a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2) …
If there is exactly one viable function that is a better function than all other viable functions, then it is the
one selected by overload resolution; otherwise the call is ill-formed
Therefore if operator<<( ostream &, int ) and operator<<( ostringstream &, mytype const & ) are both candidates for stream << value, the former matches int exactly with no conversion but the latter matches ostringstream exactly. Therefore neither can be "not worse" for all arguments, and neither candidate may be chosen.
But the code is valid because of a loophole. Your overload is not a candidate at all, except when you actually use your type in the function call. When you declare/define a friend inside a class block, it does not introduce it to any namespace scope; it merely associates it with the class scope, which allows it to be found if that class type describes one of the arguments being passed.
The standard has this to say about friend declarations, although it's in another section (14.6.5):
Friend declarations do not introduce new names into any scope…
So, MSVC tried to be nice and proactively introduced your friend to its enclosing namespace. Strike against MSVC.
However, when I attempted to add a declaration equivalent to what MSVC did "for free," Comeau and GCC nicely resolved the resulting overloading conflict — strike against them. Or is it? As it turns out, the overloaded call occurs earlier in the file than my recommended declaration. If I move the declaration before class mytype { (which requires forward-declaring mytype), then both properly complain about the ambiguity.
Using an overload before it is declared in namespace scope appears to be well and good according to §3.3-3.4 of the Standard. So actually GCC and Comeau were both in the right. The point of declaration is right after the name of the declared object. (And last I checked, self-referential function declarations can still crash GCC.) ADL invokes unqualified lookup into the enclosing namespace at a point immediately before the enclosing class. (3.4.1/8 final bullet, 3.4.1/9, 3.4.2/2a.) If the friend hasn't been declared before the class, it's legitimately not a candidate. (7.3.1.2/3) Isn't C++ a beautiful language?
How keep the simplified example on GCC, but break subsequent code.
friend ostringstream& operator<<(ostringstream& stream, const mytype& a) {
stream << (a.value);//compilation error
return stream;
}
};
ostringstream& operator<<(ostringstream& stream, const mytype& a); // <- here
Following this declaration, it will be impossible to write an int into an ostringstream.
How to break everything uniformly, with simpler declaration semantics.
class mytype; // <- here
// and here:
inline ostringstream& operator<<(ostringstream& stream, const mytype& a);
class mytype {
public:
Following this declaration, it will be impossible to write an int into an ostringstream… including the friend declarations inside class mytype {}.
Actual solution.
The stream classes are supposed to be indistinguishable. If you really want to determine whether a given stream feeds a string in memory (and you shouldn't), it's best to look at its internal streambuf object, returned by rdbuf(), which actually performs the I/O gruntwork. Even a generic ostream object can have ostringstream functionality if given a stringbuf.
if ( typeid( stream.rdbuf() ) == typeid( stringbuf * ) ) {
// this is effectively a stringstream
} else {
// not a stringstream
}
There is an overload ambiguity in the call to operator<< in the ostringstream overload.
stream << a.value;
There are a number of operator<< overloads that are members of the ostream class, which is a base class of ostringstream. One of these is declared as:
ostream& ostream::operator<<(int);
This overload is an exact match for the right-hand side (a.value is an int) but requires a derived-to-base conversion on the left-hand side (stream is an ostringstream, which is derived from ostream).
However, there is also your ostringstream overload:
ostringstream& operator<<(ostringstream&, const mytype&);
This overload is an exact match for the left-hand side (stream is an ostringstream), and a user-defined converting constructor (your mytype(int) constructor) can be used to convert a.value (an int) to a mytype.
Since one overload matches the first argument better and the other overload matches the second argument better, there is an ambiguity. You can fix this either by:
Explicitly converting the left-hand side to an ostream (using (ostream&)stream = a.value;), or
Remove the user-defined conversion by making the constructor explicit.