我有一个简单的特征功能:
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;
};
我可以考虑实现Cal::f
的4种方法并指定返回类型。
// 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不起作用?具体来说,我想知道返回类型T背后的原因不能命名一个类型,而参数类型T可以命名一个类型。编译器是否在返回和参数类型的不同上下文中工作?另外,为什么c ++ 11选择4而不是选项3?似乎选项3比选项4更直观。
答案 0 :(得分:1)
即使像C ++这样的复杂语言的编译器仍然需要从头到尾处理文件。
如果template< … >
之后的声明以T
开头,编译器需要知道T
是什么,以便在继续查找之前解析它并确定它是返回类型宣言的其余部分。
基本上,限定符Cal< Traits >::
需要在Cal
成员的任何不合格使用之前进行语法合理。使用尾随返回类型扩展语言要容易得多,后者在Cal< Traits >::
之后立即放置auto
,而不是创建用于跳过具有未知标识符的类型名称的启发式方法。
答案 1 :(得分:0)
T是Cal类模板中的typedef。它没有在全球范围内定义。以下应该可以正常作为选项3:
template <typename Traits>
typename Cal<Traits>::T Cal<Traits>::f(T a, T b) {
return a+b;
};