NTTP 的结构类型:为什么所有成员都必须是公共的?
Structural types as NTTP: why must all members be public?
在下面的示例中
template<auto V>
struct A {};
struct B {
constexpr B(int a) : value{a} {}
private:
int value{0};
};
int main() {
constexpr B b{0};
A<b> t2;
}
成员value
必须是公共的,才能使类型B
结构化,才能将其用作A
的 NTTP
。那么,没有具有私有成员的类型用作 NTTP? 这是 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1907r1.html 的真正意图吗?
这是[P1907]的真正意图吗?
P1907 的目的是正确指定两个值在模板参数上下文中等效的含义。在本文之前,等价的概念首先基于<=>
(P0732(,然后基于==
(P1185(,但是使用这些比较运算符作为基础存在很多问题(如论文中所述(。
考虑指针。我们已经有很长时间了写作的能力:
template <char const*> struct X { };
在这里,如果指针p
和q
指向具有静态存储持续时间的同一对象或两个空指针,则X<p>
和X<q>
是相同的类型(P1907还允许两者都是过去结束的指针或两者都指向同一子对象(。
现在,考虑如下类型:
struct S {
char const* b;
char const* e;
char const* c;
};
如何:
template <S> struct Y { };
工作?此类型具有所有公共成员,因此可以肯定地说它没有不变量 - 任何人都可以修改这些指针中的任何一个以指向任何内容。规则是,如果s1.b
和s2.b
是相同的指针,如果s1.e
和s2.e
是相同的指针,并且如果s1.c
和s2.c
是相同的指针,则Y<s1>
和Y<s2>
是同一类型。所有三个成对都是相同的。
现在考虑如下类型:
class String {
private:
char const* begin_;
char const* end_;
char const* capacity_;
public:
constexpr String();
constexpr String(char const*);
constexpr String(String const&);
constexpr String& operator=(String const&);
constexpr ~String();
};
此类型具有私有成员,因此强制执行一些不变量 - 并且可能对"相同"的含义有不同的理解,而不仅仅是"其所有成员都是成对等效的"。事实上,String
大致是std::string
的外观(忽略 SSO(,如果我们采用成员等效的方法,那么我们会遇到以下情况:
template <String> struct Z { };
Z<"hello"s>
每次都可能给出不同的类型 - 因为我们必须分配存储来保存字符串,并且这些底层指针可能不同。P1907的一个不小的驱动因素是,最终允许:
template <std::string> struct C;
这样,C<"hello">
不仅在翻译单元中始终是相同的类型,而且在所有翻译单元中也始终是相同的类型。基于<=>
/==
的机制不适用于这种情况。让std::string
作为非类型模板参数正常工作的唯一方法是能够有一个自定义机制,其中std::string
的作者指定等效性的基础——在这种情况下,我们甚至根本不会看容量指针,它只是基于从begin_
到end_
的字符序列(而不是指针值, 指向的值(。
这种新机制尚不存在(作者暗示了operator template
(,因此在它存在之前有两种选择:
- 删除所有类类型作为非类型模板参数 提出一种默认机制,该机制适用于某些类型,
- 但不会将不正确的等效概念添加到其他类型,即使这会阻止将某些类类型用作非类型模板参数,而成员等效规则是正确的。
我们选择了选项 2,使用"所有公共"作为执行简单、成员等效的机制......理解C++23将有这样的机制(如operator template
(允许非类型模板参数,如std::string
、std::vector<char>
、std::optional<int>
等。
答案很简单,但令人失望:C++20 不允许这样做。最终 c++23 将引入更广泛的解决方案......
- 没有类型结构绑定不起作用?
- 如何使用指针连接两种不同的节点类型(结构)?
- 无法汇总初始化类型结构的变量,其中包含在类模板中的位字段成员
- 您如何声明类型结构的堆栈?在C 中
- 访问指向相同类型结构的指针
- 静态数据类型(结构)的组织
- 创建类型结构的指针阵列
- 处理类型结构数组
- 嵌入式 C++:在 C++ 中初始化易失性类型结构
- Mac OSX的c++中的变量类型结构(oaidl.h)
- 嵌套类型:结构与类
- 如何在 python 中实现 c++ 类型结构
- 如何使用类型结构定义双端队列(双面队列)
- 删除类型结构的元素形式向量
- 从类型结构的向量中删除元素
- 在c#、c++和java中创建python弱类型结构的强类型版本
- 从较大的数据类型(结构)转换为较小的数据类型
- 使用QGLShaderProgram从Qt传递自定义类型(结构体)统一到GLSL
- 如何:公开c++数据结构/类型(结构体,枚举)供c#使用
- 按值将类型结构传递给函数,错误:声明"average"中的两个或多个数据类型!!-