Alan
Alan

Reputation: 1

Point of Instantiation for function templates

I am learning about templates in C++. In particular, i read about POIs. So i am trying out(by reading and writing) different examples. One such example which is not clear to me is given below:

template<typename T>
void g1(T p)
{

}
template<typename T>
void f1(T x)
{
g1(x); // #1: Is this point a POI for g1<T>(x)?
}
//#2: Or is this point a POI for g1<T>(x)?


//#3: Or is this point a POI for g1<T>(x)?
int main()
{
f1(7); // this point cannot be a POI 
}
// #4 I know that this point 4 is a  POI for f1<int>(int) but is this point also a POI for g<T>(x)?

In the above snippet, i know that point #4 is a POI for f1<int>(int). But is point #4 also a POI for g1<T>(x)? I know that in the statement g1(x); the name g1 is an unqualified dependent name. I also know that the POI

for a reference to a function template specialization to be immediately after the nearest namespace scope declaration or definition that contains that reference.

This is why point #4 is a POI for f<int>(int). But then similarly, point #2 should be a POI for g1(x);. But i am not sure where is the POI for g1(x);. So what are the rules for finding the POI for an unqualified dependent name like g1.

My questions are:

  1. Is point #4 also POI for g1<T>(x)? If yes then what are the rules for finding the POI for an unqualified dependent name like g1.

  2. According to the statement i quoted(which is from C++ Templates: The Complete Guide), shouldn't point #2 be a POI for g1<T>(x);. I guess this boils down to whether the statement g1(x); refers to a function template specialization. If yes, then according to the statement quoted, point #2 should be a POI for g<T>(x);. I might be wrong here.

  3. What will change if i remove the statement f1(7);. To my understanding there will be no POI in this translation unit anymore. But i am not 100% sure of this. Or removing f1(7); will make the program ill-formed now.

Upvotes: 2

Views: 183

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 474116

The point of instantiation for a function template is on the surface pretty simple: it's the place where the compiler first sees a concrete function.

g1 is a function template; it is a compiler construct which generates a family of functions based on template parameters. g1<int> is a concrete function, a product of the compiler instantiating the template g1 to produce a real function.

When the compiler sees g1(x) in f1's definition, it sees that x is an expression whose type is dependent on a template parameter. But the compiler doesn't know what the template parameter is yet. So it has no idea what g1(x) would do. Yes, it can see the function template g1, but because x is at this point unknown, it doesn't know what template parameters to g1 it would pass.

As such, it cannot instantiate the template at that point. It can only figure out how to instantiate g1 through g1(x) when f1 is itself instantiated.

Therefore, C++ defers the point of instantiation of a template function to the first place where the compiler has full knowledge of any potential template parameters. The expression g1(x) only gets meaning when an instantiation of f1 happens. Therefore, if you do something which causes f1<int> to be instantiated, g1<int> will be instantiated at the same point.

Upvotes: 1

Related Questions