声明模板成员函数 return 类型

declaring a template member function return type

我有一个简单的特征函数:

template <typename Traits>
struct Cal {
    typedef typename Traits::T T;
    static T f(T a, T b);
};

struct FTraits {
    typedef float T;
};
struct DTraits {
    typedef double T;
};

我能想到4种方式实现Cal::f并指定return类型

// option 1. compile. as inline implementation
template <typename Traits>
struct Cal {
    typedef typename Traits::T T;
    static T f(T a, T b) {
        return a+b;
    }
};
// option 2. compile
template <typename Traits>
typename Traits::T Cal<Traits>::f(T a, T b) {
    return a+b;
};
// option 3. does not compile
template <typename Traits>
T Cal<Traits>::f(T a, T b) {
    return a+b;
};
// option 4. compile
template <typename Traits>
auto Cal<Traits>::f(T a, T b) -> T {
    return a+b;
};

我相信选项 4 是在 c++11 中添加的,因为选项 3 在以前的标准中是不可能的。我的问题是,为什么选项 3 不起作用?具体来说,我想知道 return 类型 T 不能命名类型,而参数类型 T 可以命名类型的原因。编译器是否在 return 和参数类型的不同上下文中工作?另外,为什么 c++11 选择选项 4 而不是选项 3?似乎选项 3 比选项 4 更直观。

即使像 C++ 这样复杂的语言的编译器仍然需要从头到尾处理文件。

如果 template< … > 之后的声明以 T 开头,编译器需要知道 T 是什么,以便解析它并确定它是 return键入,然后继续查找声明的其余部分。

本质上,限定符 Cal< Traits >:: 在句法上需要出现在 Cal 成员的任何非限定使用之前。使用尾部 return 类型扩展语言(将 Cal< Traits >:: 紧跟在 auto 之后)比创建用于跳过具有未知标识符的类型名称的启发式要容易得多。

T 是 Cal class 模板中的一个类型定义。它不是在全球范围内定义的。以下选项作为选项 3 应该可以正常工作:

template <typename Traits>
typename Cal<Traits>::T Cal<Traits>::f(T a, T b) {
    return a+b;
};