Question

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.

Was it helpful?

Solution

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?

OTHER TIPS

These are conversions to two different types, one of which is const, one not. Constness is part of the type.

This is different than the proscription against functions with identical signatures that return different types.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top