Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion to std::string [duplicate]

Possible Duplicate:
Overload resolution failure when streaming object via implicit conversion to string

I know it's not such a good idea to do this, but I really want to know the reason why the code below does not compile (i.e. why there is "no acceptable conversion"):

#include <iostream>
#include <string>


class Test
{
public:
    operator std::string () const;
};

Test::operator std::string () const
{
    return std::string("Test!");
}

int main ()
{
    std::string str = "Blah!";
    std::cout << str << std::endl;

    Test test;

    str = test;//implicitly calls operator std::string without complaining

    std::cout << str << std::endl;

    std::cout << test;//refuses to implicitly cast test to std::string

    return 0;
}

On Visual Studio 2010 I get this error: "error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Test' (or there is no acceptable conversion)"

Does the << operator implicitly cast std::string to something else in order to make use of it? If yes, what operator do I need to overload in my class to make such a thing work? I refuse to believe that I would actually need to use operator char *.

like image 630
Mihai Todor Avatar asked Dec 14 '12 16:12

Mihai Todor


2 Answers

operator<<(std::basic_ostream&, std::basic_string) is a function template and user defined conversions are not considered during template argument deduction. You need to overload operator<< for your class.

Another option, of course, is a cast

std::cout << static_cast<std::string>(test);
like image 137
Praetorian Avatar answered Oct 21 '22 16:10

Praetorian


The problem is that std::string is a specialisation of a template, std::basic_string<char>, and the required overload of operator<< is itself a template:

template<class charT, class traits, class Allocator>
basic_ostream<charT, traits>&
    operator<<(basic_ostream<charT, traits>&& os,
               const basic_string<charT,traits,Allocator>& str);

In order to be used for template argument deduction, a user-defined type has to be an exact match; conversions are not considered.

You will need to either provide an overload of operator<< for your class, or explicitly convert to std::string.

like image 12
Mike Seymour Avatar answered Oct 21 '22 14:10

Mike Seymour