Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion operator doesn't kick in with operator overloading

Consider the following example:

#include <string>
#include <sstream>

struct Location {
    unsigned line;

    template<typename CharT, typename Traits>
    operator std::basic_string<CharT, Traits>() const {
        std::basic_ostringstream<CharT, Traits> ss;
        ss << line;
        return ss.str();
    }
};

int main() 
{
    using namespace std::string_literals;

    Location loc{42};

    std::string s1 = "Line: "s.append(loc) + "\n"s; // fine
    //std::string s2 = "Line: "s + loc + "\n"s; // error
}

The commented line causes a compilation error: no match for 'operator+'. Why? My initial thought was that it would first use operator std::string to convert and then perform the call to operator+, the same way it does for .append.

It is only one level of implicit conversion, so it should be performed and it should be taken into account, no?

Live Demo

like image 960
DeiDei Avatar asked Oct 30 '22 00:10

DeiDei


1 Answers

Your operator is templated, thus the template arguments need to be deduced. You cannot do that, since the compiler tries to match basic_string<_CharT, _Traits, _Alloc> to your Location, and it fails.

So the problem is the overloading, not the conversion, since the code actually never reaches that point.

Change this:

std::string s2 = "Line: "s + loc + "\n"s;

to this:

std::string s2 = "Line: "s + std::string(loc) + "\n"s;

and you should be fine, since if you look closely at the compiler error, it mentions:

template argument deduction/substitution failed:
prog.cc:22:32: note:   'Location' is not derived from 'const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>'
   std::string s2 = "Line: "s + loc + "\n"s; // error
                                ^~~

and other similar messages.

like image 93
gsamaras Avatar answered Nov 15 '22 06:11

gsamaras