Namespaces
Variants
Views
Actions

Dependent names

From cppreference.com
< cpp‎ | language
Revision as of 11:04, 22 November 2012 by Cubbi (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
 
 
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements
Jump statements
Functions
function declaration
lambda function declaration
function template
inline specifier
exception specifications (deprecated)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
decltype specifier (C++11)
Specifiers
cv specifiers
storage duration specifiers
constexpr specifier (C++11)
auto specifier (C++11)
alignas specifier (C++11)
Initialization
Literals
Expressions
alternative representations
Utilities
Types
typedef declaration
type alias declaration (C++11)
attributes (C++11)
Casts
implicit conversions
const_cast conversion
static_cast conversion
dynamic_cast conversion
reinterpret_cast conversion
C-style and functional cast
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 

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

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

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

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

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:

#include <iostream>
void g(double) { std::cout << "g(double)\n"; }
 
template<class T>
struct S {
    void f() const {
        g(1); // non-dependent expression, bound now
    }
};
 
void g(int) { std::cout << "g(int)\n"; }
 
int main()
{
    g(1); // calls g(int)
 
    S<int> s;
    s.f(); // calls g(double)
}


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.

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;