简体   繁体   English

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

[英]Conditional template specialization on method of a non template class

I am trying to use boost::enable_if to conditional specialize a method of a non-templated class, but failing at it. 我试图使用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
}

I get the following error: 我收到以下错误:

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  

Any pointers where I am going wrong? 任何指针我要去哪里错了?

EDIT : I tried to simplify my question too much. 编辑 :我试图简化我的问题太多了。 Adding more relevant detail. 添加更多相关细节。

  1. You must follow ODR - one definition rule. 您必须遵循ODR-一种定义规则。 So you have to have declarations of your functions also in header file. 因此,您还必须在头文件中声明函数。

  2. To use SFINAE your functions need to be template functions - not fully specialized template functions - but couple of different template functions. 要使用SFINAE,您的功能必须是模板功能-不是完全专门的模板功能-而是几个不同的模板功能。

So - see header file. 所以-请参见头文件。 Note that you have 3 different functions here - they are not specializations of each others. 请注意,这里有3种不同的功能-它们不是彼此的专业。 Thanks to SFINAE first is only active if T==float . 感谢SFINAE,仅当T==float第一个才激活。 2nd and 3rd if T==UINT - and the distinction between them is this condition: UINT==unsigned int . 如果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();
};

Then possible usage file: 然后可能的用法文件:

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

If UINT==unsigned int this code will call 1st and 2nd functions. 如果UINT==unsigned int此代码将调用第1和第2个函数。 If UINT!=usinged int the 1st and 3rd functions will be called. 如果UINT!=usinged int ,则将调用第一和第三函数。

Then your source file (Foo.cpp): 然后,您的源文件(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;
}

Since these functions do not actually depends on T - you can require from compiler to have generated code in your dedicated cpp file by template explicit instantiation instructions: 由于这些函数实际上并不依赖于T您可以要求编译器通过模板显式实例化指令在专用cpp文件中生成代码:

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

See IDEONE working example 请参阅IDEONE工作示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM