Template Specialization of Function inside of a Templated Class

后端 未结 1 1518
-上瘾入骨i
-上瘾入骨i 2021-02-10 23:47

I have a templated class and inside I have a templated function( different template parameters ) and I having issues getting the compiler to call the correct one.

Exampl

相关标签:
1条回答
  • 2021-02-11 00:31

    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)

    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>) { }
    

    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.

    Using enable_if is possible too:

    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) { }
    

    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 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.

    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.

    0 讨论(0)
提交回复
热议问题