Dependent names
Inside the definition of a template (both class template and function template), the contents of some types and the values and the types of some expressions are not known until the template is instantiated, because they depend on the template parameter.
Contents |
[edit] Dependent types
The following types are dependent types:
- template parameter
- a member of an unknown specialization
- a nested class or enum that is a member of unknown specialization
- a cv-qualified version of a dependent type
- a compound type constructed from a dependent type
- an array type constructed from a dependent type, or whose size is a value-dependent expression
- template instantiation whose name is a template parameter, or any of template arguments is a dependent type/expression
- the result of decltype() applied to a type-dependent expression
This section is incomplete Reason: explain unknown specialization/current instantiation |
This section is incomplete Reason: examples for each bullet |
[edit] Type-dependent expressions
The following expressions are type-dependent
- an expression whose any subexpression is a type-dependent expression
- an expression that contains an identifier whose type is a dependent type
- an expression that contains a dependent template instantiation
- an expression that contains a conversion function call to a dependent type
- an expression that contains a nested name that refers to a member of unknown specialization
- any cast expression to a dependent type
- new-expression that creates an object of a dependent type
- an expression that names a static data member of type array of unknown bound
- this, if the class type is a dependent type
- member access expression that refers to a member of unknown specialization
- member access expression that refers to a member of current instantiation, whose type is a dependent type
This section is incomplete Reason: examples for each bullet |
[edit] Value-dependent expressions
- an expression whose any subexpression is a value-dependent expression
- an expression that contains the name of a non-type template parameter
- an expression that contains a name declared with a dependent type
- a constant initialized from a value-dependent expression
- sizeof, alignof, or typeid of a type-dependent expression or of a dependent type
- noexcept of a type-dependent expression
- any cast expression to a dependent type or from a value-dependent expression
- an expression that names a member of unknown specialization
[edit] Binding rules
Non-dependent names are looked up and bound at the point of template definition. This binding holds even if at the point of template instantiation there is a better match:
This section is incomplete Reason: there's more to say about dependent name lookup at the point of instantiation |
[edit] The typename disambiguator for dependent names
In a template definition, a name that is dependent on a template parameter is not considered to be a type unless the keyword typename is used:
int p = 1; template <typename T> void foo (const std::vector<T> &v) { // std::vector<T>::const_iterator is a dependent name, typename std::vector<T>::const_iterator it = v.begin(); // without 'typename', the following is parsed as multiplication // of the type-dependent member variable 'const_iterator' // and some variable 'p'. Since there is a global 'p' visible // at this point, this template definition compiles. std::vector<T>::const_iterator* p; } int main() { std::vector<int> v; foo(v); // template instantiation fails: there is no member variable // called 'const_iterator' in the type std::vector<int> }
The keyword typename may only be used in this way before qualified names, e.g. T::x.
[edit] The template disambiguator for dependent names
Similarly, in a template definition, a dependent name is not considered to be a template name unless the disambiguation keyword template is used:
template<typename T> struct S { template<typename U> void foo(){} }; template<typename T> void bar() { S<T> s; s.foo<T>(); // error: < parsed as less than operator s.template foo<T>(); // OK }
The keyword template may only be used in this way after operators :: (scope resolution), -> (member access through pointer), and . (member access), the following are all valid examples:
- T::template foo<x>();
- s.template foo<x>();
- this->template foo<x>();
- typename t::template iterator<int>::value_type v;