Why is the keyword “typename” needed before qualified dependent names, and not before qualified independent names?

A name in C++ can pertain to three different tiers of entities: Types, values, and templates.

struct Foo
{
    typedef int A;                   // type
    static double B;                 // value
    template <typename T> struct C;  // template
};

The three names Foo::A, Foo::B and Foo::C are examples of all three different tiers.

In the above example, Foo is a complete type, and so the compiler knows already what Foo::A etc. refer to. But now imagine this:

template <typename T> struct Bar
{
    T::A x;
};

Now we are in trouble: what is T::A? if T = Foo, then T::A = int, which is a type, and all is well. But when T = struct { static char A; };, then T::A is a value, which doesn’t make sense.

Therefore, the compiler demands that you tell it what T::A and T::B and T::C are supposed to be. If you say nothing, it is assumed to be a value. If you say typename, it is a typename, and if you say template, it is a template:

template <typename T> struct Bar
{
    typename T::A x;    // ah, good, decreed typename

    void foo()
    {
        int a = T::B;   // assumed value, OK

        T::template C<int> z;  // decreed template
        z.gobble(a * x);
    }
};

Secondary checks such as whether T::B is convertible to int, whether a and x can be multiplied, and whether C<int> really has a member function gobble are all postponed until you actually instantiate the template. But the specification whether a name denotes a value, a type or a template is fundamental to the syntactic correctness of the code and must be provided right there during the template definition.

Leave a Comment