在模板函数中传递名称查找
有没有办法强制C ++编译器在模板实例化(而不是之前)中为给定的符号执行名称查找?
给出以下代码:
template <class T>
auto wrapper( T t ) -> decltype( f( t ) )
{
return f( t );
}
unsigned char f( int x ) { return x % 256; }
unsigned char f( unsigned char x ) { return x; }
int main( int, char ** )
{
auto x = wrapper( 3100 );
return 0;
}
有什么我可以做的(除了将f
的定义移到顶部),以便使代码编译并给出相同的结果,就好像f
所有定义在wrapper
的定义之前都可用一样?
我找不到任何东西,可能是因为我不知道如何恰当地说出这个问题。 如果有帮助, f
所有参数类型都可以假定为用户定义的类型。
有没有办法强制C ++编译器在模板实例化(而不是之前)中为给定的符号执行名称查找?
是。 首先,这个名字必须是依赖的。 用作f(t)
时, wrapper
的名称f
是相关的,因为t
是依赖于类型的。 [temp.dep] / 1:
在一个表达式中:
postfix-expression (
表达式列表选择)
在postfix-expression是一个非限定的id的情况下,unqualified-id表示一个依赖的名字if
问题是在模板本身之后声明的名称,即仅在实例化中声明,而不在定义上下文中,可以使用参数相关名称查找来单独找到。 根据[basic.lookup.argdep] / 2,你的f
重载只包含基本类型,但是它们没有与它们关联的全局名称空间:
如果T
是基本类型,则其关联的命名空间和类都是空的。
因此,如果参数与参数的类型相同,那么您声明的f
永远不会被找到。 一个小技巧可以帮助:
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) );
}
演示 。 这不是正确的方法,因为它会在更复杂的情况下失败。
这将与模板专业化一起工作。 请注意,您必须决定默认功能是什么,因为我看不到有问题。
// default function
template <class T>
unsigned char f( T x ) { return x; }
// specialization for int
template <>
unsigned char f( int x ) { return x % 256; }
int main( int, char ** )
{
auto x = f( 3100 );
return 0;
}
下面的代码不是很干净,但说明了如何使用类模板专门化来解决问题。 它保持原始接口(即f
和wrapper
可以像以前一样使用)。
谢谢你给我正确的提示。 我接受了一个不太详细的解决方案。
#include <type_traits>
template <class ...>
struct F;
template <class T>
auto wrapper( T t )
-> decltype( F<typename std::decay<T>::type>::f( t ) )
{
return F<typename std::decay<T>::type>::f( t );
}
template <>
struct F<unsigned char>
{
static unsigned char f( unsigned char x ) { return x; }
};
template <>
struct F<int>
{
static unsigned char f( int x ) { return x % 256; }
};
template <class T>
auto f( T t )
-> decltype( F<typename std::decay<T>::type>::f( t ) )
{
return F<typename std::decay<T>::type>::f( t );
}
int main( int, char ** )
{
auto x = wrapper( 3100 );
return 0;
}
链接地址: http://www.djcxy.com/p/24487.html
上一篇: pass name lookup in template function
下一篇: How to ignore hidden elements in a Bootstrap Button Group?