且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

模板类中函数的模板专业化

更新时间:2022-04-10 09:49:54

是的,显式专门化函数而不完全专门化所有外部模板是不可能的函数 - 它周围不能有任何可变部分,仍然由模板参数化)

Yes, explicitly specializing a function without fully specializing all outer template is not possible (an explicit function specialization is a real function - there can't be any "variable parts" around it that are still parameterized by a template)

一个简单的方法是使用type2type模板和重载:

A simple way is to use a type2type template together with overloading:

template<typename T> struct t2t { typedef T type; };

void Func( Parm1 arg1, Parm2, arg2 ) { Call<Parm3>(arg1, arg2, t2t<Parm3>()); }
template< class Type, class V >  void Call( Parm1 arg1, Parm2 arg2, t2t<V>) { }
template< class Type >  void Call( Parm1 arg1, Parm2 arg2, t2t<void>) { }

第二个调用重载,如果你用 t2t< void> 调用它,否则,因为第一个

Now, it will call the second Call overload if you call it with t2t<void>, and the first otherwise, because the first one is less special.

使用 enable_if

void Func( Parm1 arg1, Parm2, arg2 ) { Call<Parm3>(arg1, arg2); }

template< class Type > typename disable_if< is_same<Type, void> >::type
Call( Parm1 arg1, Parm2 arg2) { }

template< class Type > typename enable_if< is_same<Type, void> >::type 
Call( Parm1 arg1, Parm2 arg2) { }

如果 Type 是void,则取第二个值,如果 Type 又是其他值,则取第一个值。但使用不同的技术。这个被称为 SFINAE 。另一种方法,但它又添加了一个参数,这是为了演示SFINAE的工作原理:

Now, the second one is taken if Type is void, and the first one is taken if Type is something else again. But using a different technique. This one is called SFINAE. An alternative way, but which again adds one parameter is this - to demonstrate the way SFINAE works:

void Func( Parm1 arg1, Parm2, arg2 ) { Call<Parm3>(arg1, arg2); }

template< class Type >
void Call( Parm1 arg1, Parm2 arg2, char(*)[!is_same<Type, void>::value] = 0) { }

template< class Type > 
void Call( Parm1 arg1, Parm2 arg2, char(*)[ is_same<Type, void>::value] = 0) { }

如果模板参数的替换产生无效的类型或构造,则会发生SFINAE 。下面,我们尝试创建一个指向0或1的数组的指针。大小为0的数组无效,并且将导致SFINAE失败 - 如果相应的模板专用化是函数,则不会将其视为调用候选。

SFINAE happens if the substitution of a template parameter yields to an invalid type or construct. Below, we try to create a pointer to an array of size 0 or 1 respectively. An array of size 0 is not valid, and will cause an SFINAE failure - the corresponding template specialization will not be considered as a call-candidate if it is a function.

在上面的 enable_if 中,它的工作原理不同。如果 enable_if 给出从 false_type 派生的东西,那么它使它的 :: type typedef不存在。 is_same false_type 中导出类型不同的情况。然后,我们将尝试访问一个不存在的名称 - 这是一个无效的结构,因此也将是一个SFINAE失败。

In the enable_if case above, it works different. If enable_if is given something derived from false_type, then it makes its ::type typedef not existent. is_same derives itself from false_type in the case types are not the same. We would then try to access a not existent name - which is an invalid construct and would therefor be an SFINAE failure too.