有谁知道为什么main中的最后一行无法编译(注意它是编译失败):
template <typename TT> inline TT getAs();
template <> string getAs() { return "bye"; }
template <> int getAs() { return 123; }
class Foo
{
public:
template <typename TT>
inline operator TT() const { return ::getAs<TT>(); }
template <typename TT>
inline string getAs() const { return ::getAs<TT>(); }
};
Foo tempFoo() { return Foo(); }
int main()
{
Foo foo;
string testStringLocal = foo; // OK
int testIntTemp = tempFoo(); // OK
string testStringTemp = tempFoo().getAs<string>(); // OK
const string& testStringTemp2 = tempFoo(); // OK
string testStringTemp3 = tempFoo(); //.getAs<string>(); // FAIL!
}
正如我对主要内容的评论所指出的那样,
const string&
而不是字符串在VS2010上试过这个。注意上面的代码在2005年编译得很好,但我相信2010年是正确的。
如果删除模板定义和特化并简单地明确定义每个重载,则通过运算符隐式转换为字符串工作正常:
class Foo
{
public:
operator string() const { return ::getAs<string>(); }
operator int() const { return ::getAs<int>(); }
...
};
我不想使用此解决方法,因为它不太可维护。
有没有人知道另一种方法让main()的最后一行成功编译?我不认为Explicit conversion and templated conversion operator的接受答案在这里适用,因为无论是否涉及模板,都有可能进行多次转换(char *,alloc,string),而且对象是临时的这一事实似乎很重要。
编辑:这篇文章中的原始代码显示了一些类内模板专业化,这是从我的原始源创建一个独立的代码片段的人工制品(我将一些命名空间级别的专业化转移到了类和VS2010中没抱怨)。问题是不专业化。我将发布的代码修改为更接近原始代码(正如我刚才所做的那样),不使用类内专业化(当然问题仍然存在)。 Derek的回答表明它可能是VS2010特有的。
答案 0 :(得分:3)
不了解Visual C ++ 2010(我认为版本9.0),但是你不能在类本身中专门化一个模板化的成员函数。它必须在命名空间范围内完成,根据我给这段代码的更现代的编译器发出的错误。
所以,
#include <string>
using namespace std;
class Foo
{
public:
template <typename TT> inline operator TT() const;
template <typename TT> inline TT getAs() const;
};
template <> inline Foo::operator string() const { return "hi"; }
template <> inline Foo::operator int() const { return 123; }
template <> inline string Foo::getAs() const { return "bye"; }
Foo tempFoo() { return Foo(); }
int main()
{
Foo foo;
string testStringLocal = foo; // OK
int testIntTemp = tempFoo(); // OK
string testStringTemp = tempFoo().getAs<string>(); // OK
string testStringTemp2 = tempFoo(); // OK!
}
使用Visual C ++ 12.0和g ++ 4.7.2进行编译。