如何使用 C++20 概念检查模板本身的一些约束
How to use C++20 concepts to check some constraints in the template itself
抱歉,标题含糊不清,我找不到合适的词来表达它。
我试图强制 class 定义一些 functions/operators 是正确的。例如 ForwardIterator
需要有一些运算符,否则我会得到一个编译器错误。我问了这个问题 ,我得到了一个带有继承的方法,它工作得很好,但 C++20 概念似乎更直观并且给出了更好的错误。
最初的想法是:
template <typename T> concept is_ForwardIterator= requires(T x, T y)
{
x == y;
};
template <typename T>
requires is_ForwardIterator<T>
struct ForwardIterator {
};
然后每当我想实现一个前向迭代器时,我继承自 ForwardIterator
:
struct MyCustomIterator
: public ForwardIterator <MyCustomIterator>
{
bool operator ==(const MyCustomIterator& other) const;
};
但是编译器一直抱怨MyCustomIterator
不满足要求:
error: constraints not satisfied for class template 'ForwardIterator' [with T = MyCustomIterator]
note: because 'MyCustomIterator' does not satisfy 'is_ForwardIterator'
template <typename T> requires is_ForwardIterator<T> struct ForwardIterator {
^
note: because 'x == y' would be invalid: invalid operands to binary expression ('MyCustomIterator' and 'MyCustomIterator')
x == y;
当您尝试使用 CRTP 时,在基础 class 模板的编译过程中,派生的 class 不完整 。因此,询问有关其行为的大多数问题是不可能的。这包括使用概念的大部分原因。
您尝试做的事情无法以这种方式合理地完成。您可能需要一个特征 class 或其他东西,具体取决于您的目标。
问题在于,在指定 ForwardIterator
约束的地方,class T
(即 MyCustomIterator
)不完整 - 它作为 class 仅名称。
您需要延迟检查约束,直到 MyCustomIterator
完成。一种方法是 constraint on the destructor of ForwardIterator
:
template <typename T>
struct ForwardIterator {
~ForwardIterator() requires is_ForwardIterator<T> {}
};
这里唯一的问题是,在有理由实例化析构函数 ~ForwardIterator
之前不会检查它,即如果您实际上没有实例化 MyCustomIterator
对象,则不会检查它.但这在实践中应该不是问题。
在 CRTP 中,导出 class 不完整,因此无法检查其 属性。
使用 traits/concept 检查接口的一种方法是 static_assert
在 class:
之后
template <typename T> concept is_ForwardIterator= requires(T x, T y)
{
x == y;
// ...
};
struct MyCustomIterator
{
bool operator ==(const MyCustomIterator& other) const;
// ...
};
static_assert(is_ForwardIterator<MyCustomIterator>);
抱歉,标题含糊不清,我找不到合适的词来表达它。
我试图强制 class 定义一些 functions/operators 是正确的。例如 ForwardIterator
需要有一些运算符,否则我会得到一个编译器错误。我问了这个问题
template <typename T> concept is_ForwardIterator= requires(T x, T y)
{
x == y;
};
template <typename T>
requires is_ForwardIterator<T>
struct ForwardIterator {
};
然后每当我想实现一个前向迭代器时,我继承自 ForwardIterator
:
struct MyCustomIterator
: public ForwardIterator <MyCustomIterator>
{
bool operator ==(const MyCustomIterator& other) const;
};
但是编译器一直抱怨MyCustomIterator
不满足要求:
error: constraints not satisfied for class template 'ForwardIterator' [with T = MyCustomIterator]
note: because 'MyCustomIterator' does not satisfy 'is_ForwardIterator'
template <typename T> requires is_ForwardIterator<T> struct ForwardIterator {
^
note: because 'x == y' would be invalid: invalid operands to binary expression ('MyCustomIterator' and 'MyCustomIterator')
x == y;
当您尝试使用 CRTP 时,在基础 class 模板的编译过程中,派生的 class 不完整 。因此,询问有关其行为的大多数问题是不可能的。这包括使用概念的大部分原因。
您尝试做的事情无法以这种方式合理地完成。您可能需要一个特征 class 或其他东西,具体取决于您的目标。
问题在于,在指定 ForwardIterator
约束的地方,class T
(即 MyCustomIterator
)不完整 - 它作为 class 仅名称。
您需要延迟检查约束,直到 MyCustomIterator
完成。一种方法是 constraint on the destructor of ForwardIterator
:
template <typename T>
struct ForwardIterator {
~ForwardIterator() requires is_ForwardIterator<T> {}
};
这里唯一的问题是,在有理由实例化析构函数 ~ForwardIterator
之前不会检查它,即如果您实际上没有实例化 MyCustomIterator
对象,则不会检查它.但这在实践中应该不是问题。
在 CRTP 中,导出 class 不完整,因此无法检查其 属性。
使用 traits/concept 检查接口的一种方法是 static_assert
在 class:
template <typename T> concept is_ForwardIterator= requires(T x, T y)
{
x == y;
// ...
};
struct MyCustomIterator
{
bool operator ==(const MyCustomIterator& other) const;
// ...
};
static_assert(is_ForwardIterator<MyCustomIterator>);