大家好,欢迎来到IT知识分享网。
非类型模板形参中的类类型
非类型模板参数现在可以是文字类类型(可以用作constexpr变量的类型),所有基类和非静态成员都是公共的和不可变的(字面上,不应该有可变的说明符)。此类类的实例存储为const对象,甚至可以调用它们的成员函数。有一种新的非类型模板形参:派生类类型的占位符。
#include <iostream>
#include <string>
#include <stdio.h>
template<std::size_t N>
struct fixed_string{
constexpr fixed_string(const char (&s)[N+1]) {
std::copy_n(s, N + 1, str);
}
constexpr const char* data() const {
return str;
}
constexpr std::size_t size() const {
return N;
}
char str[N+1];
};
template<std::size_t N>
fixed_string(const char (&)[N])->fixed_string<N-1>;
// user-defined literals are also supported
template<fixed_string S>
constexpr auto operator""_cts(){
return S;
}
// N for `S` will be deduced
template<fixed_string S>
void f(){
std::cout << S.data() << ", " << S.size() << '\n';
}
int main()
{
f<"abc">(); // abc, 3
constexpr auto s = "def"_cts;
f<s>(); // def, 3
return 0;
}
https://wandbox.org/nojs/gcc-head
https://wandbox.org/nojs/clang-head
泛型非类型模板参数
非类型模板参数被广义为所谓的结构类型。结构类型为:
- 标量类型(算术、指针、成员指针、枚举、std::nullptr_t)
- 具有以下属性的左值引用
- 文字类类型:所有基类和非静态数据成员都是公共的和不可变的,它们的类型是结构类型或数组类型。
这允许使用浮点和类类型作为模板形参:
#include <iostream>
#include <string>
#include <stdio.h>
template<auto T> // placeholder for any non-type template parameter
struct X{};
template<typename T, std::size_t N>
struct Arr{
T data[N];
};
int main()
{
X<5> x1;
X<'c'> x2;
X<1.2> x3;
// with the help of CTAD for aggregates
X<Arr{{1,2,3}}> x4; // X<Arr<int, 3>>
X<Arr{"hi"}> x5; // X<Arr<char, 3>>
return 0;
}
这里有趣的是,非类型模板参数不是与它们的操作符==()进行比较,而是以类似位的方式进行比较(确切的规则在这里)。也就是说,它们的位表示用于比较。联合是例外,因为编译器可以跟踪它们的活动成员。如果两个联合都没有活动成员或具有相同值的活动成员,则两个联合是相等的。
#include <iostream>
#include <string>
#include <stdio.h>
#include <assert.h>
#include <string.h>
template<auto T>
struct S{};
union U{
int a;
int b;
};
enum class E{
A = 0,
B = 0
};
struct C{
int x;
bool operator==(const C&) const{ // never equal
return false;
}
};
int main()
{
constexpr C c1{1};
constexpr C c2{1};
assert(c1 != c2); // not equal using operator==()
assert(memcmp(&c1, &c2, sizeof(C)) == 0); // but equal bitwise
// thus, equal at compile-time, operator==() is not used
static_assert(std::is_same_v<S<c1>, S<c2>>);
constexpr E e1{E::A};
constexpr E e2{E::B};
// equal bitwise, enum's identity isn't taken into account
assert(memcmp(&e1, &e2, sizeof(E)) == 0);
static_assert(std::is_same_v<S<e1>, S<e2>>); // thus, equal at compile-time
constexpr U u1{.a=1};
constexpr U u2{.b=1};
// equal bitwise but have different active members(a vs. b)
assert(memcmp(&u1, &u2, sizeof(U)) == 0);
// thus, not equal at compile-time
static_assert(!std::is_same_v<S<u1>, S<u2>>);
return 0;
}
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/61002.html