I am confused about the point of instantiation with the following example:
#include <iostream>
void f(int){std::cout<<"int"<<std::endl;}//3
template <typename T>
void g(T t)
{
f(t);//4
}
void f(double){std::cout<<"double"<<std::endl;}
int main()
{
g<int>(1);//1.point of instantiation for g<int>
g<double>(1.1);//2.point of instantiation for g<double>, so f(double) is visible from here?
return 0;
}
I though f is a dependent name and 1. is the point of instantiation for g< int > and 2. is the point of instantiation for g< double >, so f(double) is visible for g(1.1), however the output is
int
int
and if I comment the declaration of f(int) at 3, gcc reports an error (not surprise) and points out f(t) at 4 is the point of instantiation(surprised!!).
test.cpp: In instantiation of ‘void g(T) [with T = int]’:
test.cpp:16:10: required from here
test.cpp:9:5: error: ‘f’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
f(t);
^
Can anyone clear the concept of point of instantiation and name binding for me please?
f(t)
is a dependent unqualified function call expression, so only functions found within the definition context and those found via ADL are candidates. f(int)
is visible within the definition context, but not f(double)
, so overload resolution resolves to f(int)
for both calls.
f(double)
cannot be found by ADL because built-in types have no associated classes or namespaces. If you passed in an argument of class type, and there was an overload of f
taking this type, ADL will be able to find it. For example:
void f(int);
template <typename T>
void g(T t)
{
f(t);
}
class A {};
void f(double);
void f(A);
int main()
{
g(1); // calls f(int)
g(1.1); // calls f(int)
g(A{}); // calls f(A)
}
f(A)
is called because it is located in the global namespace, and A
's associated namespace set is the global namespace.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With