默认函数参数值在模板中可见但不应该 (gcc)
Default function parameter value visible in template but it shouldn't (gcc)
考虑以下代码:
#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: call to function 'f' that is neither visible in the
template definition nor found by argument-dependent lookup
return f(std::forward(params)...);
这是 gcc 错误还是我遗漏了什么?即实例化点是在main()
下面的f
定义之后吗?但即使在这种情况下,它也不应该工作,因为在第二阶段只能通过 ADL 找到功能,而这里不是这种情况。
For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) except that:
For the part of the lookup using unqualified name lookup ([basic.lookup.unqual]), only function declarations from the template definition context are found.
For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.
If the call would be ill-formed or would find a better match had the lookup within the associated namespaces
considered all the function declarations with external linkage introduced in those namespaces in all translation units, not just considering those declarations found in the template definition and template instantiation
contexts, then the program has undefined behavior.
请注意,ADL 在这里甚至不起作用,因为涉及的类型是基础类型(它们的关联命名空间集是空的)。
考虑以下代码:
#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: call to function 'f' that is neither visible in the template definition nor found by argument-dependent lookup return f(std::forward(params)...);
这是 gcc 错误还是我遗漏了什么?即实例化点是在main()
下面的f
定义之后吗?但即使在这种情况下,它也不应该工作,因为在第二阶段只能通过 ADL 找到功能,而这里不是这种情况。
For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) except that:
For the part of the lookup using unqualified name lookup ([basic.lookup.unqual]), only function declarations from the template definition context are found.
For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.
If the call would be ill-formed or would find a better match had the lookup within the associated namespaces considered all the function declarations with external linkage introduced in those namespaces in all translation units, not just considering those declarations found in the template definition and template instantiation contexts, then the program has undefined behavior.
请注意,ADL 在这里甚至不起作用,因为涉及的类型是基础类型(它们的关联命名空间集是空的)。