xosp7tom
xosp7tom

Reputation: 2183

declaring a template member function return type

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

Answers (2)

user673679
user673679

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

Potatoswatter
Potatoswatter

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

Related Questions