模板类专业化的模板方法

时间:2012-02-14 11:54:32

标签: c++ linux templates g++

这是我的代码:

template<typename T1, typename T2> class MyClass
{
public:
    template<int num> static int DoSomething();
};

template<typename T1, typename T2> template<int num> int MyClass<T1, T2>::DoSomething()
{
    cout << "This is the common method" << endl;
    cout << "sizeof(T1) = " << sizeof(T1) << endl;
    cout << "sizeof(T2) = " << sizeof(T2) << endl;
    return num;
}

效果很好。但是当我尝试添加这个

template<typename T1, typename T2> template<> int MyClass<T1, T2>::DoSomething<0>()
{
    cout << "This is ZERO!!!" << endl;
    cout << "sizeof(T1) = " << sizeof(T1) << endl;
    cout << "sizeof(T2) = " << sizeof(T2) << endl;
    return num;
}

我收到了编制错误: 在«&gt;»标记之前无效的显式特化 模板ID«DoSomething&lt; 0&gt;»for«int MyClass :: DoSomething()»与任何模板声明都不匹配

我使用g ++ 4.6.1 我该怎么办?

4 个答案:

答案 0 :(得分:8)

不幸的是,您无法专门化作为类模板成员的模板,而无需专门设计外部模板:

  

C ++ 11 14.7.3 / 16:在类模板成员或出现在命名空间作用域中的成员模板的显式特化声明中,成员模板及其某些封闭类模板可能仍然未经专门化,< strong>,除非声明的封闭类模板没有明确专门化,否则声明不应明确地专门化类成员模板。

我认为您最好的选择是将额外参数添加到MyClass,然后部分专门化。

答案 1 :(得分:0)

这很可悲但却是正确的:你不能明确地专门化一个类模板,除非它的封闭类模板也明确专门化。有关详细信息,请阅读

下面我首先专门研究MyClass,一切都完成了。

#include <iostream>
using namespace std;

template<typename T1, typename T2> class MyClass
{
public:
  template<int num> static int DoSomething();
};

template<typename T1, typename T2> template<int num> int MyClass<T1, T2>::DoSomething()
{
  cout << "This is the common method" << endl;
  cout << "sizeof(T1) = " << sizeof(T1) << endl;
  cout << "sizeof(T2) = " << sizeof(T2) << endl;
  return num;
}

template<> template<> int MyClass<char, int>::DoSomething<0>()
{
  cout << "This is ZERO!!!" << endl;
  cout << "sizeof(T1) = " << sizeof(char) << endl;
  cout << "sizeof(T2) = " << sizeof(int) << endl;
  return 0;
}

int main() {
  MyClass<char, int> m;
  m.DoSomething<2>();
  m.DoSomething<0>();
  return 0;
}

输出:

This is the common method
sizeof(T1) = 1
sizeof(T2) = 4
This is ZERO!!!
sizeof(T1) = 1
sizeof(T2) = 4

EUREKA!这在MSVCPP 10上运行良好。

#include <iostream>
using namespace std;

template<typename T1, typename T2> class MyClass
{
public:
  template<int num> static int DoSomething();
  template<> static int DoSomething<0>() {
    cout << "This is ZERO!!!" << endl;
    cout << "sizeof(T1) = " << sizeof(T1) << endl;
    cout << "sizeof(T2) = " << sizeof(T2) << endl;
    return 0;
  }
};

template<typename T1, typename T2> template<int num> int MyClass<T1, T2>::DoSomething()
{
  cout << "This is the common method" << endl;
  cout << "sizeof(T1) = " << sizeof(T1) << endl;
  cout << "sizeof(T2) = " << sizeof(T2) << endl;
  return num;
}

int main() {
  MyClass<char, int> m;
  m.DoSomething<2>();
  m.DoSomething<0>();
  return 0;
}

输出:

This is the common method
sizeof(T1) = 1
sizeof(T2) = 4
This is ZERO!!!
sizeof(T1) = 1
sizeof(T2) = 4

顺便说一句,不要专业化return num;。它永远不知道num是什么。

答案 2 :(得分:0)

老问题,我知道,

但我偶然发现了当前项目中的同一个问题,并找到了一个解决方法,至少对于模板参数来说,这些参数不是类型而是值(如template <int num>)。

我的解决方案的实施:

template<class T> template<int num> void Classname<T>::methodname()
{
    if (num == 0)
    {
        //implementation for num == 0
    }
    else if (num == 1)
    {
        //implementation for num == 1
    }
    //more cases...
}

num == constant将评估为一个常量表达式,因此编译器将优化您的代码,以便为每种情况保持正确的实现。

如果我错了或者某些事情使这个问题变得糟糕,请纠正我;)

答案 3 :(得分:0)

类似于 DocValle 的回答,不依赖于可能的编译器优化

你可以使用 constexpr if 来强制编译时分支

template<class T> template<int num> void Classname<T>::methodname()
{
    if constexpr (num == 0)
    {
        //implementation for num == 0
    }
    else if constexpr (num == 1)
    {
        //implementation for num == 1
    }
    //more cases...
}