Why Don't I Need to Specify "Typename" Before a Dependent Type in C++20

Why don't I need to specify typename before a dependent type in C++20?

One of the new features in C++20 is Down with typename.

In C++17, you had to provide the typename keyword in nearly all dependent contexts to disambiguate a type from a value. But in C++20, this rule is relaxed a lot. In all contexts where you need to have a type, the typename keyword is no longer mandatory.

One such context is the return type of a function in class scope, as in your example. Others include the type in a member declaration, the type on the right-hand side of a using declaration, the parameter declaration of a lambda, the type you're passing to static_cast, etc. See the paper for the full list.


Nearly all because base-specifiers and mem-initializer-ids were always excluded, as in:

template <typename T> struct X : T::type  { }; // always ok

This is okay because, well, that needs to be a type. The paper simply extends this logic (well, it has to be a type, so let's just assume it's a type) to a lot more places that have to be types.

Why is `typename` prefix still required in such a case in C++20?

The answer is speaking loosely about what "context" means. What the feature is doing is finding places where it is grammatically impossible for anything other than a typename to appear in that location. It is those places where typename is no longer necessary.

For example, using name = X;. Grammatically, this is a type alias declaration. As such, whatever X is, the grammar requires that it be a type. If the X happens to be a name dependent on a template parameter, whatever that name is must be a type. So the grammar is unambiguous, and typename is redundant.

The syntax name<X> states that X is a template argument to the template name. But template arguments do not have to be types. A specific template may take a type as a specific argument, but grammatically, X could be an identifier referencing a variable or a template. Therefore, you must disambiguate ambiguous dependent Xs.

Where and why do I have to put the template and typename keywords?

(See here also for my C++11 answer)

In order to parse a C++ program, the compiler needs to know whether certain names are types or not. The following example demonstrates that:

t * f;

How should this be parsed? For many languages a compiler doesn't need to know the meaning of a name in order to parse and basically know what action a line of code does. In C++, the above however can yield vastly different interpretations depending on what t means. If it's a type, then it will be a declaration of a pointer f. However if it's not a type, it will be a multiplication. So the C++ Standard says at paragraph (3/7):

Some names denote types or templates. In general, whenever a name is encountered it is necessary to determine whether that name denotes one of these entities before continuing to parse the program that contains it. The process that determines this is called name lookup.

How will the compiler find out what a name t::x refers to, if t refers to a template type parameter? x could be a static int data member that could be multiplied or could equally well be a nested class or typedef that could yield to a declaration. If a name has this property - that it can't be looked up until the actual template arguments are known - then it's called a dependent name (it "depends" on the template parameters).

You might recommend to just wait till the user instantiates the template:

Let's wait until the user instantiates the template, and then later find out the real meaning of t::x * f;.

This will work and actually is allowed by the Standard as a possible implementation approach. These compilers basically copy the template's text into an internal buffer, and only when an instantiation is needed, they parse the template and possibly detect errors in the definition. But instead of bothering the template's users (poor colleagues!) with errors made by a template's author, other implementations choose to check templates early on and give errors in the definition as soon as possible, before an instantiation even takes place.

So there has to be a way to tell the compiler that certain names are types and that certain names aren't.

The "typename" keyword

The answer is: We decide how the compiler should parse this. If t::x is a dependent name, then we need to prefix it by typename to tell the compiler to parse it in a certain way. The Standard says at (14.6/2):

A name used in a template declaration or definition and that is dependent on a template-parameter is
assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified
by the keyword typename.

There are many names for which typename is not necessary, because the compiler can, with the applicable name lookup in the template definition, figure out how to parse a construct itself - for example with T *f;, when T is a type template parameter. But for t::x * f; to be a declaration, it must be written as typename t::x *f;. If you omit the keyword and the name is taken to be a non-type, but when instantiation finds it denotes a type, the usual error messages are emitted by the compiler. Sometimes, the error consequently is given at definition time:

// t::x is taken as non-type, but as an expression the following misses an
// operator between the two names or a semicolon separating them.
t::x f;

The syntax allows typename only before qualified names - it is therefor taken as granted that unqualified names are always known to refer to types if they do so.

A similar gotcha exists for names that denote templates, as hinted at by the introductory text.

The "template" keyword

Remember the initial quote above and how the Standard requires special handling for templates as well? Let's take the following innocent-looking example:

boost::function< int() > f;

It might look obvious to a human reader. Not so for the compiler. Imagine the following arbitrary definition of boost::function and f:

namespace boost { int function = 0; }
int main() {
int f = 0;
boost::function< int() > f;
}

That's actually a valid expression! It uses the less-than operator to compare boost::function against zero (int()), and then uses the greater-than operator to compare the resulting bool against f. However as you might well know, boost::function in real life is a template, so the compiler knows (14.2/3):

After name lookup (3.4) finds that a name is a template-name, if this name is followed by a <, the < is
always taken as the beginning of a template-argument-list and never as a name followed by the less-than
operator.

Now we are back to the same problem as with typename. What if we can't know yet whether the name is a template when parsing the code? We will need to insert template immediately before the template name, as specified by 14.2/4. This looks like:

t::template f<int>(); // call a function template

Template names can not only occur after a :: but also after a -> or . in a class member access. You need to insert the keyword there too:

this->template f<int>(); // call a function template

Dependencies

For the people that have thick Standardese books on their shelf and that want to know what exactly I was talking about, I'll talk a bit about how this is specified in the Standard.

In template declarations some constructs have different meanings depending on what template arguments you use to instantiate the template: Expressions may have different types or values, variables may have different types or function calls might end up calling different functions. Such constructs are generally said to depend on template parameters.

The Standard defines precisely the rules by whether a construct is dependent or not. It separates them into logically different groups: One catches types, another catches expressions. Expressions may depend by their value and/or their type. So we have, with typical examples appended:

  • Dependent types (e.g: a type template parameter T)
  • Value-dependent expressions (e.g: a non-type template parameter N)
  • Type-dependent expressions (e.g: a cast to a type template parameter (T)0)

Most of the rules are intuitive and are built up recursively: For example, a type constructed as T[N] is a dependent type if N is a value-dependent expression or T is a dependent type. The details of this can be read in section (14.6.2/1) for dependent types, (14.6.2.2) for type-dependent expressions and (14.6.2.3) for value-dependent expressions.

Dependent names

The Standard is a bit unclear about what exactly is a dependent name. On a simple read (you know, the principle of least surprise), all it defines as a dependent name is the special case for function names below. But since clearly T::x also needs to be looked up in the instantiation context, it also needs to be a dependent name (fortunately, as of mid C++14 the committee has started to look into how to fix this confusing definition).

To avoid this problem, I have resorted to a simple interpretation of the Standard text. Of all the constructs that denote dependent types or expressions, a subset of them represent names. Those names are therefore "dependent names". A name can take different forms - the Standard says:

A name is a use of an identifier (2.11), operator-function-id (13.5), conversion-function-id (12.3.2), or template-id (14.2) that denotes an entity or label (6.6.4, 6.1)

An identifier is just a plain sequence of characters / digits, while the next two are the operator + and operator type form. The last form is template-name <argument list>. All these are names, and by conventional use in the Standard, a name can also include qualifiers that say what namespace or class a name should be looked up in.

A value dependent expression 1 + N is not a name, but N is. The subset of all dependent constructs that are names is called dependent name. Function names, however, may have different meaning in different instantiations of a template, but unfortunately are not caught by this general rule.

Dependent function names

Not primarily a concern of this article, but still worth mentioning: Function names are an exception that are handled separately. An identifier function name is dependent not by itself, but by the type dependent argument expressions used in a call. In the example f((T)0), f is a dependent name. In the Standard, this is specified at (14.6.2/1).

Additional notes and examples

In enough cases we need both of typename and template. Your code should look like the following

template <typename T, typename Tail>
struct UnionNode : public Tail {
// ...
template<typename U> struct inUnion {
typedef typename Tail::template inUnion<U> dummy;
};
// ...
};

The keyword template doesn't always have to appear in the last part of a name. It can appear in the middle before a class name that's used as a scope, like in the following example

typename t::template iterator<int>::value_type v;

In some cases, the keywords are forbidden, as detailed below

  • On the name of a dependent base class you are not allowed to write typename. It's assumed that the name given is a class type name. This is true for both names in the base-class list and the constructor initializer list:

     template <typename T>
    struct derive_from_Has_type : /* typename */ SomeBase<T>::type
    { };
  • In using-declarations it's not possible to use template after the last ::, and the C++ committee said not to work on a solution.

     template <typename T>
    struct derive_from_Has_type : SomeBase<T> {
    using SomeBase<T>::template type; // error
    using typename SomeBase<T>::type; // typename *is* allowed
    };

Why do we need typename for type dependent on a template-parameter in C++

it assumes that T::bar is a static member unless typename is specified beforehand. afaict there is no technical limitation that would prevent compilers from being able to figure out during instantiation whether or not T::bar is a type, but to keep things a bit easier for compiler implementors, the decision was made. It can make more of a difference than than one might think, consider

T::bar<a,b>c;

is this a variable c of type T::bar<a,b>, or is it a less than, comma, greater than? T::bar < a followed by b > c? C++ template syntax leaves a lot to be desired.

Why typename keyword is not needed in template dependent nested type names in VS2015?

In c++20 typename is not needed there. In some contexts, the need for typename was removed, because syntactically anything there must be a type.

In particular:

A qualified name that appears in type-id, where the smallest enclosing type-id is:

  • the type in a new expression that does not parenthesize its type;

Quoted source isn't directly from the standard, but pretty reliable.

Prior to c++20 typename was needed there; it would be parsed as a value, and new value is not valid syntax. In c++20 typename is optional in that context.

Now, visual-studio-2015 has no c++20 features in it; what you are seeing there is MSVC's failure to properly implement c++11/c++14/c++17, not a c++20 extension.

C++20 No more dependent scope needed

It is a C++20 thing:

In some contexts, only type names can validly appear. In these contexts, a dependent qualified name is assumed to name a type and no typename is required:

  • A qualified name that is used as a declaration specifier in the (top-level) decl-specifier-seq of:
    • a simple declaration or function definition at namespace scope;
    • a class member declaration;
    • a parameter declaration in a class member declaration (including friend function declarations), outside of default arguments;
    • a parameter declaration of a declarator for a function or function template whose name is qualified, outside of default arguments;
    • a parameter declaration of a lambda expression outside of default arguments;
    • a parameter declaration of a requires-expression;
    • the type in the declaration of a non-type template parameter;
  • A qualified name that appears in type-id, where the smallest enclosing type-id is:
    • the type in a new expression that does not parenthesize its type;
    • the type-id in an alias declaration;
    • a trailing return type,
    • a default argument of a type template parameter, or
    • the type-id of a static_cast, dynamic_cast, const_cast, or reinterpret_cast.

see dependent_name#The_typename_disambiguator_for_dependent_names for more details.

Why is typename necessary in return type? C++

While parsing the return type (as defined in the question) we are not in the scope of Queue<T> yet. Your reasoning would be correct if you were to write

template<typename T>
auto Queue<T>::test() -> Node* {

}

The nested name qualifier of the fully qualified function name puts us into the scope of the current template specialization. Here unqualified name lookup finds Node* in the current specialization, where it is known to refer to a type.

But while parsing the return type in your question the compiler hasn't yet encountered the "current specialization" where Node* can be unambiguously assumed to name a type. All it sees is us writing a dependent name from some specialization. As such, typename is required. It's no different to us having to write

template<typename T>
typename OtherUnrelatedClass<T>::Node* Queue<T>::test() {

}

Where and why do I have to put the template and typename keywords?

(See here also for my C++11 answer)

In order to parse a C++ program, the compiler needs to know whether certain names are types or not. The following example demonstrates that:

t * f;

How should this be parsed? For many languages a compiler doesn't need to know the meaning of a name in order to parse and basically know what action a line of code does. In C++, the above however can yield vastly different interpretations depending on what t means. If it's a type, then it will be a declaration of a pointer f. However if it's not a type, it will be a multiplication. So the C++ Standard says at paragraph (3/7):

Some names denote types or templates. In general, whenever a name is encountered it is necessary to determine whether that name denotes one of these entities before continuing to parse the program that contains it. The process that determines this is called name lookup.

How will the compiler find out what a name t::x refers to, if t refers to a template type parameter? x could be a static int data member that could be multiplied or could equally well be a nested class or typedef that could yield to a declaration. If a name has this property - that it can't be looked up until the actual template arguments are known - then it's called a dependent name (it "depends" on the template parameters).

You might recommend to just wait till the user instantiates the template:

Let's wait until the user instantiates the template, and then later find out the real meaning of t::x * f;.

This will work and actually is allowed by the Standard as a possible implementation approach. These compilers basically copy the template's text into an internal buffer, and only when an instantiation is needed, they parse the template and possibly detect errors in the definition. But instead of bothering the template's users (poor colleagues!) with errors made by a template's author, other implementations choose to check templates early on and give errors in the definition as soon as possible, before an instantiation even takes place.

So there has to be a way to tell the compiler that certain names are types and that certain names aren't.

The "typename" keyword

The answer is: We decide how the compiler should parse this. If t::x is a dependent name, then we need to prefix it by typename to tell the compiler to parse it in a certain way. The Standard says at (14.6/2):

A name used in a template declaration or definition and that is dependent on a template-parameter is
assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified
by the keyword typename.

There are many names for which typename is not necessary, because the compiler can, with the applicable name lookup in the template definition, figure out how to parse a construct itself - for example with T *f;, when T is a type template parameter. But for t::x * f; to be a declaration, it must be written as typename t::x *f;. If you omit the keyword and the name is taken to be a non-type, but when instantiation finds it denotes a type, the usual error messages are emitted by the compiler. Sometimes, the error consequently is given at definition time:

// t::x is taken as non-type, but as an expression the following misses an
// operator between the two names or a semicolon separating them.
t::x f;

The syntax allows typename only before qualified names - it is therefor taken as granted that unqualified names are always known to refer to types if they do so.

A similar gotcha exists for names that denote templates, as hinted at by the introductory text.

The "template" keyword

Remember the initial quote above and how the Standard requires special handling for templates as well? Let's take the following innocent-looking example:

boost::function< int() > f;

It might look obvious to a human reader. Not so for the compiler. Imagine the following arbitrary definition of boost::function and f:

namespace boost { int function = 0; }
int main() {
int f = 0;
boost::function< int() > f;
}

That's actually a valid expression! It uses the less-than operator to compare boost::function against zero (int()), and then uses the greater-than operator to compare the resulting bool against f. However as you might well know, boost::function in real life is a template, so the compiler knows (14.2/3):

After name lookup (3.4) finds that a name is a template-name, if this name is followed by a <, the < is
always taken as the beginning of a template-argument-list and never as a name followed by the less-than
operator.

Now we are back to the same problem as with typename. What if we can't know yet whether the name is a template when parsing the code? We will need to insert template immediately before the template name, as specified by 14.2/4. This looks like:

t::template f<int>(); // call a function template

Template names can not only occur after a :: but also after a -> or . in a class member access. You need to insert the keyword there too:

this->template f<int>(); // call a function template

Dependencies

For the people that have thick Standardese books on their shelf and that want to know what exactly I was talking about, I'll talk a bit about how this is specified in the Standard.

In template declarations some constructs have different meanings depending on what template arguments you use to instantiate the template: Expressions may have different types or values, variables may have different types or function calls might end up calling different functions. Such constructs are generally said to depend on template parameters.

The Standard defines precisely the rules by whether a construct is dependent or not. It separates them into logically different groups: One catches types, another catches expressions. Expressions may depend by their value and/or their type. So we have, with typical examples appended:

  • Dependent types (e.g: a type template parameter T)
  • Value-dependent expressions (e.g: a non-type template parameter N)
  • Type-dependent expressions (e.g: a cast to a type template parameter (T)0)

Most of the rules are intuitive and are built up recursively: For example, a type constructed as T[N] is a dependent type if N is a value-dependent expression or T is a dependent type. The details of this can be read in section (14.6.2/1) for dependent types, (14.6.2.2) for type-dependent expressions and (14.6.2.3) for value-dependent expressions.

Dependent names

The Standard is a bit unclear about what exactly is a dependent name. On a simple read (you know, the principle of least surprise), all it defines as a dependent name is the special case for function names below. But since clearly T::x also needs to be looked up in the instantiation context, it also needs to be a dependent name (fortunately, as of mid C++14 the committee has started to look into how to fix this confusing definition).

To avoid this problem, I have resorted to a simple interpretation of the Standard text. Of all the constructs that denote dependent types or expressions, a subset of them represent names. Those names are therefore "dependent names". A name can take different forms - the Standard says:

A name is a use of an identifier (2.11), operator-function-id (13.5), conversion-function-id (12.3.2), or template-id (14.2) that denotes an entity or label (6.6.4, 6.1)

An identifier is just a plain sequence of characters / digits, while the next two are the operator + and operator type form. The last form is template-name <argument list>. All these are names, and by conventional use in the Standard, a name can also include qualifiers that say what namespace or class a name should be looked up in.

A value dependent expression 1 + N is not a name, but N is. The subset of all dependent constructs that are names is called dependent name. Function names, however, may have different meaning in different instantiations of a template, but unfortunately are not caught by this general rule.

Dependent function names

Not primarily a concern of this article, but still worth mentioning: Function names are an exception that are handled separately. An identifier function name is dependent not by itself, but by the type dependent argument expressions used in a call. In the example f((T)0), f is a dependent name. In the Standard, this is specified at (14.6.2/1).

Additional notes and examples

In enough cases we need both of typename and template. Your code should look like the following

template <typename T, typename Tail>
struct UnionNode : public Tail {
// ...
template<typename U> struct inUnion {
typedef typename Tail::template inUnion<U> dummy;
};
// ...
};

The keyword template doesn't always have to appear in the last part of a name. It can appear in the middle before a class name that's used as a scope, like in the following example

typename t::template iterator<int>::value_type v;

In some cases, the keywords are forbidden, as detailed below

  • On the name of a dependent base class you are not allowed to write typename. It's assumed that the name given is a class type name. This is true for both names in the base-class list and the constructor initializer list:

     template <typename T>
    struct derive_from_Has_type : /* typename */ SomeBase<T>::type
    { };
  • In using-declarations it's not possible to use template after the last ::, and the C++ committee said not to work on a solution.

     template <typename T>
    struct derive_from_Has_type : SomeBase<T> {
    using SomeBase<T>::template type; // error
    using typename SomeBase<T>::type; // typename *is* allowed
    };

How do you understand dependent names in C++

A dependent name is essentially a name that depends on a template argument.

When using templates there is a distinction between the point of definition of the template and the point of instantiation i.e. where you actually use the template. Names that depend on a template don't get bound until the point of instantiation whereas names that don't get bound at the point of definition.

A simple example would be:

template< class T > int addInt( T x )
{
return i + x.toInt();
}

where a declaration or definition of i would need to appear before the definition given above since i does not depend on the template argument T and is therefore bound at the point of definition. The definition of the toInt member of the as-yet-unknown-type x variable only has to appear before the addInt function is actually used somewhere as it is a dependent name ( technically the point of instantiation is taken as the nearest enclosing global or namespace scope just before the point of use and so it has to be available before that ).

Why is initialization of a constant dependent type in a template parameter list disallowed by the standard?

(IMHO) The most common reasons the standard disallows a specific feature are:

  1. The feature is covered by another mechanism in the language, rendering it superfluous.
  2. It contradicts existing language logic and implementation, making its implementation potentially code breaking.
  3. Legacy: the feature was left out in the first place and now we've built a lot without it that it's almost forgotten (see partial function template specialization).

Difficulty of implementation is rarely a factor, though it may take some time for compiler implementations to catch up with evolution on the "hard" stuff.

You could always wrap your non type template parameter in another type:

template < typename T1, typename T2 > 
struct Demo {}; // primary template

template < typename T >
struct Demo<T, integral_constant<T, 0>> {}; // specialization

I doubt this hack falls into case 1. Case 3 is always a possibility so lets examine case 2. To do this, we have to know which are the related rules the standard imposes on class templates partial specializations.

14.5.5 Class template partial specializations


  1. A non-type argument is non-specialized if it is the name of a non-type parameter. All other non-type arguments are specialized. (C1)

  2. Within the argument list of a class template partial specialization, the following restrictions apply:

    • A partially specialized non-type argument expression shall not involve a template parameter of the partial specialization except when the argument expression is a simple identifier. (C2)


Related Topics



Leave a reply



Submit