3

有谁知道为什么 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!
}

正如我对主要行的评论所指出的,

  • 从 Foo 到字符串的隐式转换在非临时对象(例如 foo)上编译得很好,
  • 以及转换为 int (或 long 等)时的临时对象
  • 通过方法转换为字符串时它确实工作正常
  • 以及如果类型const string&不是字符串

在VS2010上试过这个。请注意,上面的代码在 2005 年编译得很好,但我相信 2010 年是正确的。

如果我删除模板定义和特化并简单地明确定义每个重载,则通过运算符隐式转换为字符串可以正常工作:

class Foo
{
public:
    operator string() const { return ::getAs<string>(); }
    operator int()    const { return ::getAs<int>(); }
    ...
};

我不想使用这种解决方法,因为它的可维护性较差。

有谁知道让 main() 的最后一行成功编译的另一种方法?我不认为对显式转换和模板化转换运算符的公认答案适用于此,因为无论是否涉及模板,都可能进行多种转换(char *、alloc、string),而且对象是临时对象的事实似乎很重要.

编辑:这篇文章中的原始代码显示了一些类内模板专业化,这是从我的原始源中为 SO 创建独立代码片段的人工制品(我将一些命名空间级专业化移动到类中,VS2010 没有抱怨)。问题在于专业化。我修改了发布的代码以更接近原始代码(就像我刚刚所做的那样),不使用课堂专业化(当然问题仍然存在)。Derek 的回答表明它可能特定于 VS2010。

4

1 回答 1

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 编译良好。

于 2014-01-03T06:27:26.940 回答