Re: Frustrated in autocast failure
On Mar 8, 6:11 pm, "Old Wolf" <oldw...@inspire.net.nz> wrote:
Here is some simpler code that demonstrates the problem:
#include <iostream>
#include <string>
struct S
{
std::string z;
operator std::string () const { return z; }
// operator int *() const { return 0; }
};
int main()
{
S s;
std::cout << s;
}
The program fails to compile, unless the (int *) line is commented
back in.
It seems to me that S->(int *)->(void *) to match ostream::operator<<
(void *) is a trickier sequence than S->std::string to match
operator<<(ostream &, std::string const &) ! In fact the gcc
output shows that the latter function is not even in the candidates
list.
Nor would a std::ostream operator<< overload for a std::string
argument ever be likely to appear as a candidate function - because no
such routine actually exists. So one explanation why an S object can
be streamed to std::cout when it implicitly converts to an int pointer
- but not when it can convert only to a std::string - is simple:
std::ostream defines an operator<< overload that matches the former
(as a const void * argument) but does not define any method that can
match the latter.
Now of course it is possible for a C++ program to stream std::strings
to std::cout (see "Hello, world"). A C++ program is able to do so
courtesy of a std::string non-member function template (see ?21.3.8.9
[string.io].) And it is the fact that a std::string argument invokes a
function template operator<< while an int pointer does not in the
sample program - that accounts for the behavior observed in the
program above. Essentially, C++ allows an argument to be implicitly
converted in order to match a function - but does not allow an
implicit conversion in order to instantiate a function template that
would match the implicitly-converted argument.
Now one could get around this issue by providing a non-template
function that would call the function template in the Standard
Library:
std::ostream& operator<<(std::ostream& os, std::string& s)
{
return std::operator<<(os, s);
}
But it makes much more sense to overload operator<< for the exact type
of its argument (in this case, type "S") - rather than to rely on
implicit conversions to ensure that the matching overloaded operator<<
is found.
Greg
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]