所以我有一个看起来像这样的课程:
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多分钟尝试各种各样的事情。 我该怎么做?
答案 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
,则可以使用只有两个选项的标记类型0
和1
,并使用以下内容发送:
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>())
{}
我省略了其中一个重载。作为一个正交变化,我修改了参数类型以引用字符串(不需要继续移动key
和ivec
对象,我们知道调用者,我们可以使用字符串,因为我们请)。