Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can two implicit conversions exist that differ only by return constness?

Consider the following code:

#include <string>

class WrapperString
{
public:
    WrapperString(const std::string& str) : str_(str) {}

    operator std::string() const { return str_; }
    operator const std::string() const { return str_; }

    std::string get() const { return str_; }
    // error C2373: 'WrapperString::get' : redefinition; different type modifiers
    // const std::string get() const { return str_; }

private:
    std::string str_;
};

int main (int, char *[])
{
    WrapperString w( "Hello" );
    std::string foo = w; // disabling either implicit conversion makes this work
    return 0;
}

Why does WrapperString actually compile given the two implicit conversions differ only by their constness? One cannot achieve this result by declaring a named method.

BTW, this is VS2010.

EDIT : Just to be clear, I added the get() methods as a logical counterexample as to why it doesn't make sense to have two implicit conversions.

like image 758
MarkB Avatar asked Jan 11 '23 07:01

MarkB


1 Answers

Why does WrapperString actually compile given the two implicit conversions differ only by their constness

The return type is not the only difference: operator std::string and operator const std::string are names of these two functions, and they happen to be different in this case, unlike the names of the get member functions.

$3[basic]/4: "A name is a use of [...] conversion-function-id"

$12.3.2.1[class.conv.fct]/1:

conversion-function-id:
    operator conversion-type-id

If you'd like, you could call them by those names using plain function call syntax.

 std::string s1 = w.operator std::string();
 std::string s2 = w.operator const std::string();
 std::string s3 = w.get(); // which get?
like image 72
Cubbi Avatar answered Jan 29 '23 02:01

Cubbi