Reputation: 2183
I have a simple traits function:
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;
};
I can think of 4 ways to implement Cal::f
and specify the return type.
// 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;
};
I believe option 4 is added in c++11 as option 3 is not possible in the previous standard. My question is, why option 3 does not work? Specifically, I wonder the reason behind that return type T cannot name a type, whereas argument type T can name a type. Does compiler work in different contexts for return and argument types? Also, why c++11 choose option 4 over option 3? It seems option 3 is more intuitive than option 4.
Upvotes: 3
Views: 1160
Reputation: 1366
T is a typedef inside the Cal class template. It isn't defined at global scope. The following should work fine as option 3:
template <typename Traits>
typename Cal<Traits>::T Cal<Traits>::f(T a, T b) {
return a+b;
};
Upvotes: 0
Reputation: 137930
Even compilers of a sophisticated language like C++ still need to process the file from the beginning to the end.
If the declaration after template< … >
begins with T
, the compiler needs to know what T
is, in order to parse it and determine that it's a return type, before proceeding to find the rest of the declaration.
Essentially, the qualifier Cal< Traits >::
needs to come syntactically before any unqualified uses of members of Cal
. It's much easier to extend the language with trailing return types, which place Cal< Traits >::
immediately after auto
, than to create a heuristic for skipping over type names with unknown identifiers.
Upvotes: 1