默认函数参数值在模板中可见,但不应 (gcc)

Default function parameter value visible in template but it shouldn't (gcc)

本文关键字:gcc 参数 函数 默认      更新时间:2023-10-16

考虑以下代码:

#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++抛出了预期的消息,这是正确执行两阶段名称查找的编译器所期望的:

错误:对函数"f"的调用在依赖于参数的查找未找到模板定义返回f(std::forward(params)…);

这是一个gcc错误还是我遗漏了什么?也就是说,在f的定义之后实例化的点在main()之下吗?但即使在这种情况下,它也不应该起作用,因为在第二阶段,只能通过ADL找到功能,而这里的情况并非如此。

〔temp.dep.candidate〕:

对于后缀表达式是依赖名称的函数调用,使用常用查找规则([basic.lookup.uqual]、[basic.lookup.argdep])查找候选函数,但以下情况除外:

  • 对于使用非限定名称查找的查找部分([basic.lookup.uqual]),只找到模板定义上下文中的函数声明。

  • 对于使用关联命名空间的查找部分([basic.lookup.argdep]),只找到在模板定义上下文或模板实例化上下文中找到的函数声明。

如果调用格式不正确,或者如果在关联的命名空间中进行查找,会找到更好的匹配考虑了所有转换单元中那些名称空间中引入的具有外部链接的所有函数声明,而不仅仅是考虑模板定义和模板实例化中的声明上下文,则程序具有未定义的行为

注意,ADL在这里甚至不起作用,因为所涉及的类型是基本的(它们的一组关联名称空间是空的)。