我正在尝试元编程,以便可以在编译时计算阶乘。这是第一个版本:
template <int N>
struct Fac {
static const int val;
};
template <>
struct Fac<1> {
static const int val;
};
非常清楚。然后我就考虑不使用const,这样就导致了成员变量的定义在外面。然而第一个问题就出来了:
template <int N>
struct Fac {
static int val;
};
template <>
struct Fac<1> {
static int val;
};
template <int N>
int Fac<N>::val = N * Fac<N - 1>::val;
template <> // <- error: extraneous 'template<>' in declaration of variable 'val'
int Fac<1>::val = 1;
错误是“变量‘val’声明中存在无关的‘template<>’”。
然后我发现没有template <>
它也能工作:
template <int N>
struct Fac {
static int val;
};
template <>
struct Fac<1> {
static int val;
};
template <int N>
int Fac<N>::val = N * Fac<N - 1>::val;
int Fac<1>::val = 1;
一开始我以为template <> struct Fac<1>
是多余的,所以把它去掉了,但我发现
template <>
必须加在
Fac<1>::val
前面,如下:
template <int N>
struct Fac {
static int val;
};
template <int N>
int Fac<N>::val = N * Fac<N - 1>::val;
template <>
int Fac<1>::val = 1;
嗯,我可以将其理解为模板类的完整规范。
然而,当添加另一个模板参数来证明我的观点时,又出错了:
template <int N, int M>
struct Fac {
static int val;
};
template <int N, int M>
int Fac<N, M>::val = N * Fac<N - 1, M>::val;
template <int M> // <- error: nested name specifier 'Fac<1, M>::' for declaration does not refer into a class, class template or class template partial specialization
int Fac<1, M>::val = 1;
错误是“声明的嵌套名称说明符'Fac::'不引用类、类模板或类模板部分特化<1, M>”。
更正为添加Fac<1, M>
部分规范版本的定义如下:
template <int N, int M>
struct Fac {
static int val;
};
template <int M>
struct Fac<1, M> {
static int val;
};
template <int N, int M>
int Fac<N, M>::val = N * Fac<N - 1, M>::val;
template <int M>
int Fac<1, M>::val = 1;
我请求帮忙解释所有这些现象。我的环境:
苹果 clang 版本 15.0.0 (clang-1500.3.9.4)
目标:x86_64-apple-darwin23.5.0
线程模型:posix
安装目录:/Library/Developer/CommandLineTools/usr/bin