wim*_*aan 2 c++ templates c++20
在下面的例子中
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;
}
Run Code Online (Sandbox Code Playgroud)
成员value
必须是公共的才能使类型B
结构化以将其用作 NTTP for A
.
那么,没有可以用作 NTTP 的具有私有成员的类型吗?这是http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1907r1.html的真正意图吗?
这是[P1907]的真正意图吗?
P1907 的目的是正确指定在模板参数上下文中两个值等效的含义。在本文之前,等价的概念首先基于<=>
( P0732 ) 然后基于==
( P1185 ),但是使用这些比较运算符作为基础有很多问题(如论文中所述)。
考虑指针。我们已经有很长一段时间的写作能力了:
template <char const*> struct X { };
Run Code Online (Sandbox Code Playgroud)
而在这里,X<p>
并且X<q>
是同一类型的,如果指针p
和q
指向具有静态存储持续时间或两个空指针同一个对象(P1907也允许既要过去最末端的指针或两个相同的子对象的能力)。
现在,考虑一个类型:
struct S {
char const* b;
char const* e;
char const* c;
};
Run Code Online (Sandbox Code Playgroud)
怎么会:
template <S> struct Y { };
Run Code Online (Sandbox Code Playgroud)
工作?此类型具有所有公共成员,因此可以肯定地说它没有不变量 - 任何人都可以修改这些指针中的任何一个以指向任何内容。这些规则是那么Y<s1>
和Y<s2>
是相同的类型,如果s1.b
和s2.b
是相同的指针,并且如果s1.e
和s2.e
是相同的指针,并且如果s1.c
和s2.c
是相同的指针。三对都是一样的。
现在考虑一个类型:
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();
};
Run Code Online (Sandbox Code Playgroud)
这种类型有私有成员,因此,强制执行一些不变量 - 并且可能对“相同”必须意味着什么有不同的理解,而不是简单地“其所有成员都是成对等价的”。实际上,String
大致是这样的std::string
(忽略 SSO),如果我们采用成员等效的方法,那么我们会遇到以下情况:
template <String> struct Z { };
Run Code Online (Sandbox Code Playgroud)
Z<"hello"s>
每次可能会给出不同的类型——因为我们必须分配存储空间来保存字符串,而那些底层指针可能会有所不同。P1907 的一个重要驱动因素是希望最终允许:
template <std::string> struct C;
Run Code Online (Sandbox Code Playgroud)
这C<"hello">
不仅在一个翻译单元内始终是相同的类型,而且在所有翻译单元中也始终是相同的类型。并且基于<=>
/的机制==
不适用于这种情况。并且std::string
作为非类型模板参数正确工作的唯一方法是能够有一个自定义机制,其中作者std::string
指定等价基于什么——在这种情况下,我们甚至不会看容量指针,它只是基于从begin_
到的字符序列end_
(不是指针值,指向值)。
那个新机制还不存在(作者已经暗示了operator template
),所以在它存在之前有两个选择:
我们选择了选项 2,使用“all public”作为进行简单的、按成员的等价的机制......并理解 C++23 将具有这样的机制(如operator template
)以允许非类型模板参数类型喜欢std::string
,std::vector<char>
,std::optional<int>
等。