Hug*_*ugh 79 c++ template-function name-lookup argument-dependent-lookup
C++规范的哪一部分限制参数依赖查找在相关命名空间集合中查找函数模板?换句话说,为什么main下面的最后一次调用无法编译?
namespace ns {
struct foo {};
template<int i> void frob(foo const&) {}
void non_template(foo const&) {}
}
int main() {
ns::foo f;
non_template(f); // This is fine.
frob<0>(f); // This is not.
}
Run Code Online (Sandbox Code Playgroud)
Kor*_*icz 83
这部分解释了它:
C++标准03 14.8.1.6:
[注意:对于简单的函数名称,即使函数名称在调用范围内不可见,依赖于参数的查找(3.4.2)也适用.这是因为调用仍然具有函数调用的语法形式(3.4.1).但是当使用具有显式模板参数的函数模板时,除非在调用点处有一个具有该名称的函数模板,否则调用没有正确的语法形式.如果看不到这样的名称,则调用语法不完善,并且参数依赖查找不适用.如果某些此类名称可见,则应用依赖于参数的查找,并且可以在其他名称空间中找到其他函数模板.
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
}
Run Code Online (Sandbox Code Playgroud)
从 c++20 开始,adl 也适用于显式函数模板。这是提案: P0846R0:不可见的 ADL 和函数模板:
不是要求用户使用模板关键字,而是提出了对查找规则的修订,以便正常查找不会产生结果或找到一个或多个函数且后跟 aa "<" 的名称将被视为如果已找到函数模板名称并且会导致执行 ADL。
目前,只有 GCC 9 实现了此功能,因此您的示例可以编译。
我想改进稍微接受的答案。在 OP 问题中不清楚,但标准(由 Kornel 引用)的重要部分是这个(强调我的):
但是当使用带有显式模板参数的函数模板时,调用没有正确的语法形式
所以被禁止的是依赖 ADL 并使用显式模板参数。不幸的是,使用非类型模板参数需要使用显式参数(除非它们具有默认值)。
以下是显示此内容的示例代码。:
#include <string>
#include <utility>
namespace C {
struct B { };
template<class T> void f(T t){}
}
void g(C::B b) {
f(b); // OK
//f<C::B>(b); // ill-formed: not a function call, but only
// because explicit template argument were used
std::string s;
move(s); // OK
//move<std::string&>(s); // Error, again because
// explicit template argument were used
std::move<std::string&>(s); // Ok
}
int main()
{
C::B b;
g(b);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3825 次 |
| 最近记录: |