理解非类型模板参数

tao*_*ocp 12 c++ templates c++11

我有问题理解以下段落Per C++ 11 Standard N3485 Section 14.1.7.我认为理解基本原理而不是记住事实更为重要.

非类型模板参数不应声明为具有浮点,类或void类型.
[例如:

template<double d> class X; // error
template<double* pd> class Y; // OK
template<double& rd> class Z; // OK
Run Code Online (Sandbox Code Playgroud)

- 末端的例子]

我对此规则有一些疑问:

  1. 有没有理由为什么floating point类型不能用作模板参数?这背后的理由是什么?我知道在C++ 11之前就是这样,对于C++ 11标准来说也是如此.

  2. 为什么它是确定使用pointerreference浮点类型为非模板参数,而不是原始的浮点类型?这里最大的区别是什么?

谢谢您的帮助.

And*_*owl 8

有没有理由说浮点类型不能用作模板参数?这背后的理由是什么?

虽然我无法给出最终的理由,但我可以想象,专门用于接受浮动指针值作为参数的模板会出现问题.

浮点数之间的等式比较是棘手的(在某种意义上它有时会产生意外结果),并且在匹配特化时,编译器必须在提供的参数和模板专用的值之间执行相等性检查.

另一个类似的问题是确定相同类模板的两个实例是否实际上是同一类型:

template<double D>
struct X
{
    // ...
};

int main()
{
    X<3.0> x;
    X<some_constant_expression()> y;
}
Run Code Online (Sandbox Code Playgroud)

xy同一类的实例?要做出决定,必须在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
}
Run Code Online (Sandbox Code Playgroud)

另外,根据C++ 11标准的第14.4/1段:

两个模板ID指的是相同的类或函数if

- [...]

- 它们对应的整数或枚举类型的非类型模板参数具有相同的值和

- [...]

- 它们对应的引用类型的非类型模板参数引用相同的外部对象或函数

- [...]

[ 例如:

template<class E, int size> class buffer { / ... / };
buffer<char,2*512> x;
buffer<char,1024> y;
Run Code Online (Sandbox Code Playgroud)

声明x并且y属于同一类型,[...]

上面显示确定同一类模板的两个不同实例是否实际上是同一个类需要在用作模板参数的常量表达式之间进行相等性检查.

  • 我不会说浮动poitn比较是棘手的,至少不是编译器部分.事实上它非常简单.但它通常会给人类带来非常惊喜的结果,因此使用浮点模板对于devolpers来说简直是不可预测的. (2认同)