This is the statement from ISO C++ Standard 14.6.4.1 Point of instantiation
4.If a virtual function is implicitly instantiated, its point of instantiation
is
There seems always tons of questions with regards to instantiation context.
The example given by MSalters is problematic:
template void foo() {
T() + T();
}
consider the following code:
#include
using namespace std;
template void foo() {
T() + T();
}
class A {};
void operator +(const A&, const A&)
{
cout << "Called operator+(const A&, const A&)" <();
}
That compiles and runs on all compilers, but if you put the class A definition into a namespace:
#include
using namespace std;
template void foo() {
T() + T();
}
namespace {
class A {};
}
void operator+(const A&, const A&)
{
cout << "operator+(const N::A&, const N::A&)" << endl;
}
int main()
{
foo();
}
Clang will fail to compile, but VC++ and gcc compiles. Why? which compiler conforms to the spec?
Frankly, I don't know. Some compiler, like gcc even contradicts itself in this area. Consider the following code:
#include
using namespace std;
template void foo() {
g(T());
}
namespace {
class A {};
}
void g(A a)
{
cout << "g(A)" << endl;
}
int main()
{
foo();
}
Simply change from "operator+" to a function named "g", gcc fails to compile???Why???
If the Spec is correct, then why GCC cannot find 'g'?
6.The instantiation context of an expression that depends on the template arguments is the set of declarations with external linkage
declared prior to the point of instantiation of the template
specialization in the same translation unit.
When I was reading Bjarne Stroustrup's "The C++ Programming Language, 4th Edition", 26.3.5 Template and Namespaces, he has this example:
namespace N{
class A{};
char f(A);
}
char f(int);
template
char g(T t)
{
return f(t); //choose f() depending on what T is
}
char f(double);
char c1 = g(N::A()); //causes N::f(N::A) to be called
char c2 = g(2); //causes f(int) to be called
char c3 = g(2.1); //causes f(int) to be called, f(double) not considered
Here, f(t) is clearly dependent, so we cannot bind f at the point of definition. To generate a specialization for g(N::A), the compiler looks in namespace N for functions called f() and fins N::f(N::A).
The f(int) is found because it is in scope at the point of definition of the template. The f(double) is not found because it is not in scope at the point of definition of the template, and argument-dependent lookup does not find a global function takes only arguments of built-in types.
So it's a mess!