关于非模板类方法的条件模板专门化

时间:2015-03-09 16:47:57

标签: c++ templates boost template-specialization enable-if

我正在尝试使用boost :: enable_if来条件化一个非模板化类的方法,但是却失败了。

//OSSpecific.h
...
//If some OS
typedef unsigned int UINT;
//else
typedef unsigned long long UINT;
...

//Foo.h
...
#include <OSSpecific.h>
...
class Foo
{
   public:
          ...
          template <typename T>
          returnThis<T>* bar();
}
/******************************************************************/
//Foo.cpp
...
template<>
returnThis<float>* bar()
{
}

//Use this if some condition is true
template<>
returnThis<int>* Foo::bar<boost::disable_if_c<boost::is_same<int, UINT>::value >::type>()
{
    //Do something
}

    //Use this if some condition is true
template<>
returnThis<long long>* Foo::bar<boost::disable_if_c<boost::is_same<long long, UINT>::value >::type>()
{
    //Do something
}

我收到以下错误:

Foo.cpp : error C2785: 'returnType<T> *Foo::bar(void)' and 'returnType<T> *Foo::bar(void)' have different return types         
            with                                                                                                                                                                                                                                          
            [                                                                                                                                                                                                                                             
                T=int                                                                                                                                                                                                                                
            ]                                                                                                                                                                                                                                             
            Foo.h : see declaration of 'Foo::bar'                                                
            Foo.cpp : see declaration of 'Foo::bar'                                                                                                                     
    Foo.cpp : error C2910: 'Foo::bar' : cannot be explicitly specialized  

我出错的任何指示?

编辑:我试图过多地简化我的问题。添加更多相关细节。

1 个答案:

答案 0 :(得分:1)

  1. 您必须遵循ODR - 一个定义规则。所以你必须在头文件中声明你的函数。

  2. 要使用SFINAE,您的功能需要是模板功能 - 不是完全专业化的模板功能 - 而是几种不同的模板功能。

  3. 所以 - 请参阅头文件。请注意,这里有3种不同的功能 - 它们不是彼此的特殊功能。感谢SFINAE,首先只有T==float才有效。第2和第3,如果T==UINT - 它们之间的区别是这个条件:UINT==unsigned int

    class Foo
    {
    public:
    
        template <typename T>
        typename boost::enable_if<boost::is_same<T,float>,returnThis<float>*>::type 
        bar();
    
        template <typename T>
        typename boost::enable_if_c<boost::is_same<T,UINT>::value and boost::is_same<UINT,unsigned int>::value,
        returnThis<UINT>*>::type 
        bar();
    
        template <typename T>
        typename boost::enable_if_c<boost::is_same<T,UINT>::value and not boost::is_same<UINT,unsigned int>::value,
                 returnThis<UINT>*>::type 
        bar();
    };
    

    然后可能的用法文件:

    int main() {
        Foo f;
        f.bar<float>();
        f.bar<UINT>();
        return 0;
    }
    

    如果UINT==unsigned int此代码将调用第1和第2个函数。如果UINT!=usinged int将调用第1和第3个函数。

    然后你的源文件(Foo.cpp):

    template <typename T>
    typename boost::enable_if<boost::is_same<T,float>,returnThis<float>*>::type 
    Foo::bar()
    {
        cout << "bar<T==float>()\n";
        return 0;
    }
    
    template <typename T>
    typename boost::enable_if_c<boost::is_same<T,UINT>::value and boost::is_same<UINT,unsigned int>::value,
    returnThis<UINT>*>::type 
    Foo::bar()
    {
        cout << "bar<T==UINT and UINT==usigned int>()\n";
        return 0;
    }
    
    template <typename T>
    typename boost::enable_if_c<boost::is_same<T,UINT>::value and not boost::is_same<UINT,unsigned int>::value,
    returnThis<UINT>*>::type 
    Foo::bar()
    {
        cout << "bar<T==UINT and UINT!=usigned int>()\n";
        return 0;
    }
    

    由于这些函数实际上并不依赖于T - 您可以要求编译器通过模板显式实例化指令在您的专用cpp文件中生成代码:

    template returnThis<float>* Foo::bar<float>();
    template returnThis<UINT>* Foo::bar<UINT>();
    

    请参阅IDEONE working example