【问题标题】:Conditional template specialization on method of a non template class非模板类方法的条件模板特化
【发布时间】:2015-03-09 16:47:57
【问题描述】:

我正在尝试使用 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  

我哪里出错了?

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

【问题讨论】:

  • 不清楚您在这里要完成什么。 boost::is_same&lt;int, long&gt;::type 将永远是 integral_constant&lt;bool, false&gt;
  • 如果intlong 是同一类型,我想禁用。固定。
  • 但是...intlong 绝不是同一类型,即使它们在特定平台上的宽度相同。
  • 但它们绝不是同一类型,即使sizeof(int) == sizeof(long)

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


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

  2. 要使用 SFINAE,您的函数需要是模板函数 - 不是完全专用的模板函数 - 而是几个不同的模板函数。

所以 - 见头文件。请注意,您在这里有 3 个不同的功能 - 它们不是彼此的专业化。感谢 SFINAE first 只有在T==float 时才有效。 2nd 和 3rd if 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,此代码将调用第一个和第二个函数。如果UINT!=usinged int 将调用第一个和第三个函数。

然后你的源文件(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

【讨论】:

  • 1.我在哪里遇到部分专业化? 2. 我想将代码拆分到单独的 H/CPP 文件中。
  • @armundle 你改变了问题。但无论如何 - 你必须遵循一个定义规则(ODR),否则你的程序是未定义的行为。您不能在头文件中拥有通用模板功能和在 cpp 文件中完全专业化。您必须在头文件中说明(声明)您将拥有完全专业化。
  • @armundle 您不能将 SFINAE 用于非模板函数/类 - 这是不可能的。
  • 嗯,方法是模板化的。
  • 不要将完全专业化的模板视为真正的模板。请参阅我的更新以回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 2010-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多