vso*_*tco 6 c++ g++ language-lawyer
请考虑以下代码:
#include <utility>
void f(int, int);
void g(int, int);
struct functor
{
    template<typename... T>
    void operator()(T&&... params)
    {
        return f(std::forward<T>(params)...);
    }
};
int main()
{
    functor()(1); // can use the default value here, why?!
    // g(1); // error here as expected, too few arguments
}
void f(int a, int b = 42) {}
void g(int a, int b = 24) {}
这是一个围绕函数调用的瘦包装器.但是,在内部functor::operator(),f没有已知的第二个参数的默认值(它只main在定义之后可见),因此代码不应该编译.g ++ 5.2虽然成功编译了它,但是clang ++吐出了一个预期的消息,一个人期望正确执行两阶段名称查找的编译器:
error:调用函数'f',它在模板定义中既不可见,也不是由参数依赖查找返回f(std :: forward(params)...);
这是一个gcc bug还是我在这里遗漏了什么?即,是f下面定义后的实例化点main()?但即使在这种情况下,也不应该工作,因为在第二阶段,只能通过ADL找到该功能,而这不是这里的情况.
对于后缀表达式是从属名称的函数调用,使用通常的查找规则([basic.lookup.unqual],[basic.lookup.argdep])查找候选函数,除了:
对于使用非限定名称查找 ([basic.lookup.unqual]) 的查找部分,仅找到模板定义上下文中的函数声明。
对于使用关联命名空间 ([basic.lookup.argdep]) 的查找部分,仅找到在模板定义上下文或模板实例化上下文中找到的函数声明。
如果调用格式不正确或找到更好的匹配,则关联命名空间内的查找会考虑所有翻译单元中这些命名空间中引入的具有外部链接的函数声明,而不仅仅是考虑在模板定义和模板中找到的那些声明实例化上下文,则程序具有未定义的行为。
请注意,ADL 甚至在这里不起作用,因为涉及的类型是基本的(它们的关联命名空间集是空的)。