Templated operator operator string () does not compile

The following compilations are in VS 2005, but not in 2010 or 2012:

#include <string> template <typename TT> TT getAs(); template <> std::string getAs() { return "bye"; } template <> int getAs() { return 123; } class Foo { public: template <typename TT> TT getAs() const { return ::getAs<TT>(); } template <typename TT> operator TT() const { return ::getAs<TT>(); } }; Foo tempFoo() { return Foo(); } int main() { Foo foo; std::string testStringLocal = foo; // OK in 2010, FAIL in 2012 int testIntTemp = tempFoo(); // OK std::string testStringTemp = tempFoo().getAs<std::string>(); // OK const std::string& testStringTemp2 = tempFoo(); // OK std::string testStringTemp3 = tempFoo(); // FAIL! } 

The compiler complains about two lines of main() that the conversion is not possible. But if I replaced the operator TT() template definition with a set of equivalent overloads,

 class Foo { public: template <typename TT> TT getAs() const { return ::getAs<TT>(); } operator std::string() const { return ::getAs<std::string>(); } operator int() const { return ::getAs<int>(); } }; 

then everything builds perfectly. Note based on the main() lines marked OK that this problem is specific to the TT template operator when the line is an AND template parameter (in 2010, but not in 2012) a temporary one is involved.

Is this invalid code? Why is this true in some cases?

+7
c ++ string templates operator-keyword
source share
1 answer

There seems to be ambiguity between string copy constructors.

Using this line resolves the ambiguity:

std::string testStringLocal = (const std::string&)foo;

The same thing happens with operator= :

 std::string testStringLocal; // define empty string testStringLocal = (const std::string&)foo; //OK testStringLocal = foo; // Fail in all VS compilers (VS2010, 2012, 2013) 

I don't know why std::string behaves differently than other classes, most likely a wealth of constructors and assignment operators.

When the compiler is given several parameters to perform the throw, in which case a double cast ( Foo โ†’ string โ†’ const string& ), it will work. It can also select Foo int const string& or something like that.

+1
source share

All Articles