Name Resolution for Dependent Types
The first rule applying to dependent names is the use of the typename keyword. typename is used for qualified names in template definitions to tell the compiler that the given qualified name identifies a type, as in the following example. For more information, see typename.
// template_name_resolution1.cpp
#include <stdio.h>
template <class T> class X
{
public:
void f(typename T::myType* mt) {}
};
class Yarg
{
public:
struct myType { };
};
int main()
{
X<Yarg> x;
x.f(new Yarg::myType());
printf("Name resolved using typename keyword.");
}
Output
Name resolved using typename keyword.
Another rule is that name lookup for dependent names examines names from both the context of the template definition (in the following example, this context would find myFunction(char)) and the context of the template instantiation. In the following example, the template is instantiated in main, so the MyNamespace::myFunction is visible from the point of instantiation and is picked as the better match. If MyNamespace::myFunction were renamed, myFunction(char) would be called instead.
All names are resolved as if they were dependent names. Because this behavior could change in future versions of the compiler, it is recommended that such names be fully qualified if there is any possible conflict.
//template_name_resolution2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
void myFunction(char)
{
cout << "Char myFunction" << endl;
}
template <class T> class Class1
{
public:
Class1(T i)
{
// If replaced with myFunction(1), myFunction(char)
// will be called
myFunction(i);
}
};
namespace MyNamespace
{
void myFunction(int)
{
cout << "Int MyNamespace::myFunction" << endl;
}
};
using namespace MyNamespace;
int main()
{
Class1<int>* c1 = new Class1<int>(100);
}
Output
Int MyNamespace::myFunction