浮点类型不能作为模板参数有什么原因吗?这背后的原理是什么?
虽然我无法给出最终的原因,但我可以肯定地想象,专门接受一个浮动指针值作为参数的模板会出现问题。
浮点数之间的相等比较很棘手(从某种意义上说,它有时会给出意想不到的结果),并且在匹配特化时,编译器必须在提供的参数和模板所针对的值之间执行相等检查专业的。
另一个类似的问题是确定同一类模板的两个实例是否实际上是同一类型:
template<double D>
struct X
{
// ...
};
int main()
{
X<3.0> x;
X<some_constant_expression()> y;
}
x 和 y 是同一个类的实例吗?要确定这一点,必须在 3.0 和 some_constant_expression() 之间执行相等性检查。
为什么可以使用指针或浮点类型的引用作为非模板参数,而不是原始浮点类型?
对于上述场景,关于指针的答案很简单:指针是整数值,指针之间的比较是明确定义的。
关于引用,有证据表明它们实际上被视为指针:
#include <type_traits>
double a = 0.0;
double b = 0.0;
template<double& D>
struct X : std::false_type { };
template<>
struct X<a> : std::true_type { }
int main()
{
static_assert(X<a>::value, "!"); // Does not fire
static_assert(X<b>::value, "!"); // Fires
}
此外,根据 C++11 标准的第 14.4/1 段:
两个 template-ids 引用同一个类或函数,如果
——[...]
——它们对应的整数或枚举类型的非类型模板参数具有相同的值并且
——[...]
——它们对应的引用类型的非类型模板参数指的是同一个外部对象
或函数和
——[...]
[ 例子:
template<class E, int size> class buffer { / ... / };
buffer<char,2*512> x;
buffer<char,1024> y;
声明x 和y 属于同一类型,并且[...]
上面表明,要确定同一个类模板的两个不同实例是否实际上是同一个类,需要在用作模板参数的常量表达式之间进行相等性检查。