是否有某种方法可以强制 C++ 编译器在模板实例化期间(而不是之前)对给定符号执行名称查找?
是的。首先,名称必须是依赖的。使用 as 时的名称f
是依赖的,因为它依赖于类型。[温度.dep]/1:wrapper
f(t)
t
在以下形式的表达式中:
后缀表达式
(
表达式列表 选项 )
其中postfix-expression是unqualified-id,
unqualified-id表示从属名称,如果
- 表达式列表中的任何表达式都是包扩展(14.5.3),
- 表达式列表中的任何表达式都是依赖于类型的表达式 (14.6.2.2),或者
- 如果unqualified-id是一个模板 ID,其中任何模板参数都依赖于模板参数。
问题是在模板本身之后声明的名称,即仅在实例化而不是定义上下文中,只能使用参数相关名称查找来找到。您的f
重载仅采用基本类型,但根据 [basic.lookup.argdep]/2,那些没有与之关联的全局命名空间:
如果T
是基本类型,则其关联的命名空间和类集都是空的。
因此,f
如果参数与参数的类型相同,则永远找不到您声明的 s。一个小技巧可以帮助:
template <typename T>
struct refwrap
{
T&& t;
refwrap(T&& t) : t(std::forward<T>(t)) {}
operator T&&() {return std::forward<T>(t);}
};
template <typename T>
auto make_refwrap( T&& t ) -> refwrap<T> // making use of reference collapsing
{ return {std::forward<T>(t)}; } // inside refwrap to get forwarding
此模板在全局命名空间中声明时,将导致 ADL 考虑它。改写wrapper
如下:
template <class T>
auto wrapper( T t ) -> decltype( f( make_refwrap(t) ) )
{
return f( make_refwrap(t) );
}
演示。但是,这不是正确的方法,因为它在更复杂的情况下会失败。