Totally incorrect. There is only one stage of template
instantiation. When (and where, which is an important point)
depends on how it is used. I think you're confounding name
lookup with instantiation.
Name lookup is done in two phases. (At least if the compiler
is conform—VC++ still gets this wrong.) The first occurs
when the compiler parsed the template definition; the second
when the template is instantiated. Whether a symbol is looked
up in the first phase or the second depends on whether it is
dependent or not. The rules determining this are fairly
complicated, but in general:
If it is a function name, and one or more of its arguments
depend on a template argument, the function name is dependent,
and it will be looked up (and function overload resolution) will
occur on instantiation, and not before.
If the name is qualified by a template argument (e.g.
T::something
, where T
is a template argument), it is
dependent.
In a member of a class template, if there is a dependent base
class (a base class which in some way depends on the template
argument), anything to the right of this->
is dependent.
(The actual rules are considerably more complicated, but the
above is a rough approximation, and probably sufficient for most
uses.)
EDIT:
Just some examples of the difference:
class MyType {};
void func0( double d )
{
std::cout << "called func0( double )" << std::endl;
}
void func1( double, MyType const& )
{
std::cout << "called func1( double )" << std::endl;
}
template <typename T>
int funcT( T const& param )
{
func0( 42 ); // non-dependent
func1( 42, param ); // dependent
}
void func0( int d )
{
std::cout << "called func0( int )" << std::endl;
}
void func1( int, MyType const& )
{
std::cout << "called func1( int )" << std::endl;
}
int
main()
{
funcT( MyType() );
return 0;
}
The output should be
called func0( double )
called func1( int )
The call to func0
in funcT
is non-dependent, so name lookup
occurs only at the point where the template was defined, and
not later, when it is instantiated. At that point, there is
only one func0
, so it gets called.
The call to func1
infuncT
is dependent (since its second
argument depends on the template argument), so there will be an
additional name lookup at the point of instantiation
(immediately following main
, in this case). This additional
lookup only uses ADN, but since one of the arguments is defined
in global namespace, ADN will look in global namespace, and find
the second declaration of func1
as well (which will then be
chosen by overload resolution, because it is a better match).
Note that I can't verify this, because at the moment, I only
have access to VC++11, which is broken. And it is subtle, so
it's quite possible I've missed something. The general rule is
to avoid such ambiguities.
Note that if func0
were not declared before the template
definition, the code should not compile. From experience, when
moving from pre-standard compilers (or VC++), this is the most
common cause of errors.
Another common case where this sometimes surprises:
template <typename Base>
class Derived : public Base
{
public:
Derived()
{
init(); // Non-dependent lookup, will NOT find any
// function init() in Base!!!
this->init() // Dependent lookup, WILL find
// Base::init, if it exists.
Base::init() // Also dependent.
}
};
Typically, if you're using this pattern, and developing on
a pre-standard compiler like VC++, you'll get a number of
compiler errors when you move to a more modern compiler.
They're easily fixed by adding the this->
. However, if
there is also a global function init
visible when the template
is defined, you will call this, and not the function in the
base class. If you choose meaningful names for your functions,
and put global functions in namespaces, you'll probably not get
hit very often by this silent change of semantics, but bewarned.