具有两个整数参数的类的部分特化

时间:2015-04-09 07:13:47

标签: c++ templates partial-specialization

所以我有一个看起来像这样的课程:

template <unsigned short MODE, unsigned int N = 128>
  class AESLocker {
  public:

    //Default Constructor
    AESLocker() : ENCRYPTION_KEY_LENGTH(N) {
      //Blah blah
    }

    //Contructor
    AESLocker(std::string key, std::string ivec);

我正在尝试使用#defines文件中提到的MODE来实现不同的功能。

但是,我没有为2种模式制作两个不同的构造函数。即我想部分专门化构造函数。

  //constructor
  template<unsigned short MODE, unsigned int N>
  AESLocker<MODE, N>::AESLocker(std::string key, std::string ivec)  {
    //blah
  }

上面的模板目前用于所有模式和所有N.我想要的是专门用于MODE而不是N.即我想要一个构造函数用于所有N用于模式1而另一个构造函数用于所有N用于模式2。 / p>

我花了30多分钟尝试各种各样的事情。 我该怎么做?

1 个答案:

答案 0 :(得分:1)

构造函数是特殊函数,但它们仍然是函数。该语言不允许模板函数的部分特化,因此您不能部分地专门化构造函数。

如果不同版本之间的更改发生在正文(而不是初始化列表)中,那么您可以将该逻辑移动到其他私有函数并使用其他机制调用它。我想到了标签发送:

  // Make these private
  template <unsigned short MODE, unsigned int N>
  void AESLocker<MODE, N>::init(std::string key, std::string ivec, Int2Type<1>) {
      // Specialization for MODE == 1
  }
  template <unsigned short MODE, unsigned int N>
  template <int X>
  void AESLocker<MODE, N>::init(std::string key, std::string ivec, Int2Type<X>) {
      // Generic for all other modes
  }
  // Dispatch based on MODE
  template<unsigned short MODE, unsigned int N>
  AESLocker<MODE, N>::AESLocker(std::string key, std::string ivec)  {
    init(std::move(key), std::move(N), Int2Type<MODE>());
  }

请注意,我使用了通用Int2Type,强制使用模板化init作为一般情况,但如果您只想区分1,则可以使用只有两个选项的标记类型01,并使用以下内容发送:

Int2Type<MODE == 1>()

在这种情况下,init的两个重载都是非模板化的。请注意,除了语法开销之外没有实际区别,因为函数是按需生成的,这意味着每init的特化只会生成一个AESLocker


正如Jarod42所提到的,在C ++ 11及更高版本中你也可以使用转发构造函数来做同样的事情:

// private constructors
template <unsigned short MODE, unsigned int N>
AESLocker<MODE, N>::AESLocker(std::string & key, std::string & ivec, Int2Type<0>) 
: // initializer list
{ // constructor body
}
// public constructor
template <unsigned short MODE, unsigned int N>
AESLocker<MODE, N>::AESLocker(std::string key, std::string ivec)
: AESLocker(std::move(key), std::move(ivec), IntToType<MODE>())
{}

我省略了其中一个重载。作为一个正交变化,我修改了参数类型以引用字符串(不需要继续移动keyivec对象,我们知道调用者,我们可以使用字符串,因为我们请)。