c++ - 如何检查一个类是否完全符合给定的一组特征?

标签 c++ templates iterator traits

假设我正在编写一个自定义容器并想为其提供一个 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!
};

https://godbolt.org/z/5DwiaT

如果您真的想检查您是否正确实现了所需的功能和特征,这当然无法在编译时检查,需要编写一些测试。


句法要求与语义要求

请注意,概念,特别是迭代器概念,声明了句法要求语义要求。虽然基于 requires 语法声明的语法要求可以在编译时进行静态检查,但语义要求只是该类型要遵循的“注释”,不是也不能在编译时检查。另一方面,算法和编译器决策可能基于这样一个事实,即据说实现特定概念的类型遵循其语义要求。

例如,bidirectional_­iterator定义为:

23.3.4.12 Concept bidirectional_­iterator [iterator.concept.bidir]

  1. 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>;
         };
  1. A bidirectional iterator r is decrementable if and only if there exists some q such that ++q == r. Decrementable iterators r shall be in the domain of the expressions --r and r--.

  2. Let a and b be equal objects of type I. I models bidirectional_­iterator only if:

    (3.1) If a and b 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 still true

    (3.1.4) bool(++(--a) == b)

    (3.2) If a and b are incrementable, then bool(--(++a) == b).

如上所示,对于据说要实现 bidirectional_iterator 的给定迭代器,项目符号 #1 可以在编译时检查,而项目符号 #2 和 #3 则不能。


1 在 C++20 之前也应该可行,以类似的方式实现您自己的 SFINAE 受限模板

关于c++ - 如何检查一个类是否完全符合给定的一组特征?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59459529/

相关文章:

C++11 std::tuple 到 std::array 转换导致可变参数模板崩溃

c++ - 如何在类中实现标准迭代器

c++ - 带有两个 mpf_t 的 gmp pow

c++ - 在 VC++ 中解决 hid.lib "unresolved external symbol"链接器错误

c++ - 在子进程还活着时读取它的输出

python - Python 中的迭代器 (iter()) 函数。

c++ - 指针未定义

c++ - 我正在尝试打印我的阵列,但没有得到我想要的结果

html - 是否有工具可以将任何网站转换成其框架正在使用的模板?

c++ - 函数指针作为模板类函数的输入参数