Name binding is the process of finding the declaration for each name that is explicitly or implicitly used in a template. The compiler might bind a name in the definition of a template, or it might bind a name at the instantiation of a template.
template<class T> class U : A<T>
{
typename T::B x;
void f(A<T>& y)
{
*y++;
}
};
The dependent names in this example are the base
class A<T>, the type name T::B,
and the variable y.#include <iostream>
using namespace std;
void f(double) { cout << "Function f(double)" << endl; }
template <class A> struct container{ // point of definition of container
void member1(){
// This call is not template dependent,
// because it does not make any use of a template parameter.
// The name is resolved at the point of definition, so f(int) is not visible.
f(1);
}
void member2(A arg);
};
void f(int) { cout << "Function f(int)" << endl; }
void h(double) { cout << "Function h(double)" << endl; }
template <class A> void container<A>::member2(A arg){
// This call is template dependent, so qualified name lookup only finds
// names visible at the point of instantiation.
::h(arg);
}
template struct container<int>; // point of instantiation of container<int>
void h(int) { cout << "Function h(int)" << endl; }
int main(void){
container<int> test;
test.member1();
test.member2(10);
return 0;
}
The output of this example: Function f(double)
Function h(double)
The point of definition of a template is located immediately before its definition. In this example, the point of definition of the template container is located immediately before the keyword template. Because the function call f(1) does not depend on a template parameter, the compiler considers names declared before the definition of the template container. Therefore, the function call f(1) calls f(double). Although f(int) is a better match, it is not in scope at the point of definition of container.
The point of instantiation of a template is located immediately before the declaration that encloses its use. In this example, the point of instantiation of container<int> is the location of the explicit instantiation. Because the qualified function call ::h(arg) depends on the template argument arg, the compiler considers names declared before the instantiation of container<int>. Therefore, the function call h(arg) calls h(double). It does not consider h(int), because this function is not in scope at the point of instantiation of container<int>.
template <class T, class U> int h(T t, U u, decltype(t+u) v);
In this example, the compiler issues an error message
if the operand t+u is invalid after the instantiation
of the function template h.For more information, see The decltype(expression) type specifier (C++11)