[英]ADL fails (or not done?) for function with additional (non deduced) template parameter
namespace N {
class C {};
template<typename X>
char const * found(X && x) {
return "found";
}
template<typename, typename X>
char const * notfound(X && x) {
return "not found";
}
}
这定义了具有类C
和两个函数模板的名称空间N
found
有一个模板参数,可以从函数参数中推导出来。 notfound
有一个额外的模板参数,无法推断出来。
给出以下测试代码( 在ideone上 ):
#include <iostream>
int main() {
N::C object;
std::cout
<< found(object) << std::endl
<< notfound<bool>(object) << std::endl // ERROR
<< notfound<bool, N::C>(object) << std::endl; // ERROR
}
我假定参数依赖查找会发现二者found
和notfound
通过最内层的命名空间(这是N
参数类型的) N::C
。
然而:
prog.cpp: In function ‘int main()’:
prog.cpp:21:6: error: ‘notfound’ was not declared in this scope
<< notfound<bool>(object) << std::endl
^~~~~~~~
prog.cpp:21:6: note: suggested alternative:
prog.cpp:12:15: note: ‘N::notfound’
char const * notfound(X && x) {
^~~~~~~~
(注释掉未notfound<bool>(object)
调用后,未notfound<bool, N::C>(object)
错误相同)
为什么notfound
通过ADL发现?
背景:我正在为一些包装类实现一个get
函数,所有这些都与std::get(std::tuple)
相似。 包装类是一个实现细节,它位于一些名称空间lib::aspect::part::impl
。 我不希望库的用户指定using lib::aspect::part::impl::get
,原因很明显。
因为函数调用具有显式指定的模板参数的函数模板,所以必须通过普通查找找到模板的名称; 直到那个ADL无法启动。
来自标准: $ 17.8.1 / 8显式模板参数规范[temp.arg.explicit]
(强调我的)
[注意:对于简单的函数名称,即使函数名称在调用范围内不可见,依赖于参数的查找也适用。 这是因为调用仍然具有函数调用的句法形式([basic.lookup.unqual])。 但是当使用带有显式模板参数的函数模板时,除非在调用点处有一个具有该名称的函数模板,否则调用没有正确的语法形式 。 如果看不到这样的名称,则调用语法不完善,并且参数依赖查找不适用。 如果某些此类名称可见,则应用依赖于参数的查找,并且可以在其他名称空间中找到其他函数模板。 [例如:
namespace A { struct B { }; template<int X> void f(B); } namespace C { template<class T> void f(T t); } void g(A::B b) { f<3>(b); // ill-formed: not a function call A::f<3>(b); // well-formed C::f<3>(b); // ill-formed; argument dependent lookup applies only to unqualified names using C::f; f<3>(b); // well-formed because C::f is visible; then A::f is found by argument dependent lookup }
- 结束例子] - 结束说明]
最后一句给出了可能的解决方法; 您可以在任何位置添加函数模板的声明,以使名称对于被调用是可见的。 例如
template<typename>
void notfound();
int main() {
N::C object;
std::cout
<< found(object) << std::endl
<< notfound<bool>(object) << std::endl
<< notfound<bool, N::C&>(object) << std::endl; // btw the 2nd template argument should be N::C&
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.