以下编译在VS 2005中,但未在2010年或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!
}
编译器抱怨两行main()
无法进行转换。但是,如果我用一组等效的重载替换operator TT()
的模板定义,
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>(); }
};
然后一切都很好。请注意,基于标记为OK的main()
行,当字符串为模板参数时,此问题特定于模板运算符TT AND(在2010年,但不在2012年),涉及临时。
这不是有效的代码吗?为什么在某些情况下有效?
答案 0 :(得分:1)
字符串的复制构造函数之间似乎存在歧义。
使用此行解决了歧义:
std::string testStringLocal = (const std::string&)foo;
operator=
也是如此:
std::string testStringLocal; // define empty string
testStringLocal = (const std::string&)foo; //OK
testStringLocal = foo; // Fail in all VS compilers (VS2010, 2012, 2013)
我不知道为什么std::string
的行为与其他类不同,很可能是构造函数和赋值运算符的丰富。
当为编译器提供多个选项来执行强制转换时,在这种情况下为double cast
(Foo
- &gt; string
- &gt; const string&
)失败。它也可以选择Foo
- &gt; int
- &gt; const string&
或类似的东西。