假设我正在编写一个自定义容器并想为其提供一个 RandomAccessIterator
。
template<class T>
class MyContainer
{
public:
class RandomAccessIterator
{
/*
... operators, constructors, etc...
*/
};
RandomAccessIterator begin();
RandomAccessIterator end();
/*
... class implementation ...
*/
};
现在,如何检查我刚刚编写的迭代器是否与标准库算法 100% 兼容?一个明显的解决方案是简单地尝试一个:
MyContainer<int> list;
std::sort(list.begin(), list.end());
...并验证它是否编译并产生了预期的结果。
考虑到这一点,我不确定它是否是一个可靠的“特征符合性”测试,而这正是这个问题的意义所在。如果我忘记提供任何必需的方法/运算符,编译器会总是提示吗?如果没有,确保我的类型完全实现给定特征的最佳方法是什么?
@Edit:该帖子不再将标准库称为“STL”,正如评论中指出的那样是不正确的。
最佳答案
我会说这是可能的,基于 C++20 iterator concepts 1:
template<std::input_iterator T>
using validate_input_iterator = T;
这会编译失败:
struct meow {
struct iterator{};
private:
typedef validate_input_iterator<iterator> v; // fails here
};
但是下面的编译:
struct meow: private std::string { // string has an input iterator
// struct iterator{};
private:
typedef validate_input_iterator<iterator> v; // passes!
};
如果您真的想检查您是否正确实现了所需的功能和特征,这当然无法在编译时检查,需要编写一些测试。
句法要求与语义要求
请注意,概念,特别是迭代器概念,声明了句法要求和语义要求。虽然基于 requires
语法声明的语法要求可以在编译时进行静态检查,但语义要求只是该类型要遵循的“注释”,不是也不能在编译时检查。另一方面,算法和编译器决策可能基于这样一个事实,即据说实现特定概念的类型遵循其语义要求。
例如,bidirectional_iterator
定义为:
23.3.4.12 Concept bidirectional_iterator [iterator.concept.bidir]
- The
bidirectional_iterator
concept adds the ability to move an iterator backward as well as forward.template<class I> concept bidirectional_iterator = forward_iterator<I> && derived_from<ITER_CONCEPT(I), bidirectional_iterator_tag> && requires(I i) { { --i } -> same_as<I&>; { i-- } -> same_as<I>; };
A bidirectional iterator
r
is decrementable if and only if there exists someq
such that++q == r
. Decrementable iteratorsr
shall be in the domain of the expressions--r
andr--
.Let
a
andb
be equal objects of typeI
.I
modelsbidirectional_iterator
only if:(3.1) If
a
andb
are decrementable, then all of the following are true:(3.1.1)
addressof(--a) == addressof(a)
(3.1.2)
bool(a-- == b)
(3.1.3) after evaluating both
a--
and--b
,bool(a == b)
is stilltrue
(3.1.4)
bool(++(--a) == b)
(3.2) If
a
andb
are incrementable, thenbool(--(++a) == b)
.
如上所示,对于据说要实现 bidirectional_iterator
的给定迭代器,项目符号 #1 可以在编译时检查,而项目符号 #2 和 #3 则不能。
1 在 C++20 之前也应该可行,以类似的方式实现您自己的 SFINAE 受限模板
关于c++ - 如何检查一个类是否完全符合给定的一组特征?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59459529/