point of instantiation and name binding

2020-03-04 03:41发布

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?

1条回答
够拽才男人
2楼-- · 2020-03-04 03:58

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.

查看更多
登录 后发表回答