Name lookup for overloaded functions defined later

你离开我真会死。 提交于 2019-12-06 03:47:14

问题


I noticed strange behavior regarding function lookup when relying on a function to be defined later:

#include <iostream>

template <typename T>
void foo(const T&)
{
    std::cout << "Basic" << std::endl;
}

template <typename T>
void bar()
{
    T x;
    foo(x);
}

void foo(const int& x)
{
    std::cout << "int:" << x << std::endl;
}

int main()
{
    bar<int>();
}

Output:

Basic

For some reason, I expected the use of foo inside bar to find the overload below it. Moving the overload of foo to above bar makes the output the desired int:0 (or just writing a declaration).

This same behavior does not appear to apply to overloading a binary operator:

#include <iostream>

struct Foo {} foo;

template <typename T>
void operator<<(const Foo&, const T&)
{
    std::cout << "Basic" << std::endl;
}

template <typename T>
void bar()
{
    T x;
    foo << x;
}

void operator<<(const Foo&, const int& x)
{
    std::cout << "int:" << x << std::endl;
}

int main()
{
    bar<int>();
}

Output:

int:0

I have two questions, the first is: Why is the behavior like this and why is it different for operator overloading? The second is: If I have a named function (like my use of foo), is there a way to write a function bar in such a way to discover overloaded foos declared later in a translation unit?


回答1:


Welcome to the world of the most famous two phase lookup, and weirdo rules.

I'm sure there is no difference on operator and function cases just for the second you used one more argument. Try what happens if for the first version you also add another parameter with struct Foo...

Two phased lookup means that for dependent names when the template is compiled, it looks around and remember the set of visible functions. In your case that finds nothing. Then in the instantiation context there is another lookup, following the ADL (argument-dependent lookup) rules. That only. It means first collecting "associated namespaces" of the arguments, then look for more candidates in those namespaces.

In your case the only argument is int, and it has no associated namespaces, so nothing is found again. In the second case you also have Foo that drags :: with it, and your operator is found in ::.



来源:https://stackoverflow.com/questions/17433468/name-lookup-for-overloaded-functions-defined-later

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!