假设我们有以下类模板:
template<size_t S>
struct A
{
char str[S];
};
template<typename T>
class B
{
T t;
public:
void init(); // Should initialize the 't' member in some a way.
};
现在,如果我用一些非模板类型专门化init
作为B
模板的参数,这是可以的。但是,如果不指定其S
值,我就不能用A
作为B
的参数来专门化它。也就是说,我想做这样的事情:
template<>
void B<A<S>>::init()
{
// Initialize the 't.str'. For example:
memset(t.str, 0, S);
}
要提供执行特定于B<A<???>>
的部分专门化,实际上需要为类提供这样一个部分专门化:
#include <cstddef>
#include <cstring>
#include <iostream>
template<std::size_t S>
struct A
{
char str[S];
};
template<typename T>
class B
{
T t;
public:
void init(); // Should initialize the 't' member in some a way.
};
template<std::size_t S>
class B<A<S>> {
using T = A<S>;
T t;
public:
void init(); // Should initialize the 't' member in some a way.
};
template<std::size_t S>
void B<A<S>>::init()
{
// Initialize the 't.str'. For example:
std::memset(t.str, 0, S);
std::cout << "Initialized B<A<" << S << ">>n";
}
int main() {
B<A<3>> b;
b.init();
}
请注意,您的代码有两个关键区别:
- 类模板
template<std::size_t S> class B<A<S>>
存在部分特殊化 - 该类模板的
init
成员函数现在可以定义为template<std::size_t> void B<A<S>>::init() { /* ... */ }
如果您的用例中没有其他实例化有效,则可以省略类模板B
的基本用例定义,并将其替换为template<typename T> class B;
。
实时查看
由于结构体A
应该负责其成员的构建和销毁,我建议您执行以下操作:
template <size_t S = 5>
struct A {
A() {
memset(str, 0, S);
}
char str[S];
};
然后你可以有:
template<>
void B<A<>>::init()
{}
更新
正如@NathanOliver所指出的,结构A
的默认构造函数甚至不需要。以下也适用:
template <size_t S = 5>
struct A {
char str[S]{};
};
并且,由于初始化char
数组的责任传递给结构体A
,因此您不需要模板专门化。