C++的模板可以接受非类型参数,也就是接受一个值作为参数。但是能够接受的范围有限,基本上局限在具有内部链接属性的值,集中在整型值,比如各种整数,以及也为整型的指针值。
p0732r0也就是Class Types in Non-Type Template Parameters - Open-Std.oRg提倡让模板非类型参数可以接受类实例。这个特性已经进入C++20。
p0732r0中举的例子,跟David Vandevoorde在How do you pass a string literal as a parameter to a C++ template class?的回答采用的例子相同。都是展示如何以类实例作为非类型参数传给模板。
David举的例子:
template<FixedString str> struct X {
};
#include <compare>
#include <algorithm>
template<int N> struct FixedString {
constexpr FixedString(char const (&s)[N]) {
std::copy_n(s, N, this->elems);
}
constexpr std::strong_equality
operator<=>(FixedString const&) const = default;
char elems[N];
};
template<int N> FixedString(char const(&)[N])->FixedString<N>;
除了传类实例给模板以外,上面的代码还用到了飞船运算符<=>这个C++20的特性,用来自动生成强对等性的比较方法。
有了FixedString的定义,你可以写出这样的代码:
FixedString msg("a message");
C++17引入了模板参数自动推导功能,所以不用显示写FixedString<10>
。因此,你也可以写:
X<"a message"> x;
编译器会自动推导出X<“a message”>其实是X<FixedString<10>>
。
David还提到很多草案细节,这边就不赘述了。
Named Template Arguments一文的作者举了另外一些例子,可能更简单一点:
struct Point {
int x = 0;
int y = 0;
};
template <Point> // ok in C++20
void takes_tmpl_point();
takes_tmpl_point<{.x=1, .y=2}>(); // x=1, y=2
takes_tmpl_point<{.y=3}>(); // x=0, y=3
takes_tmpl_point<{.x=4}>(); // x=4, y=0
takes_tmpl_point<{.y=5, .x=6}>(); // ill-formed
这样看起来,是不是更清爽一点?
cppreference: Template parameters and template arguments所提到C++20对非类型模板参数的改进:
a floating-point type;
a literal class type with the following properties:
all base classes and non-static data members are public and non-mutable and
the types of all bases classes and non-static data members are structural types or (possibly multi-dimensional) array thereof.
其他
- (C++20) String literals as non-type template parameters example?
- https://github.com/hanickadot/compile-time-regular-expressions
- https://botondballo.wordpress.com/2018/03/28/trip-report-c-standards-meeting-in-jacksonville-march-2018/
- String literal NTTPs got pulled. See https://botondballo.wordpress.com/2018/03/28/trip-report-c-standards-meeting-in-jacksonville-march-2018/
- What is C++20’s string literal operator template?
(本篇完)