版权所有 © 2019 T. Zachary Laine
根据 Boost 软件许可协议 1.0 版分发。(请参阅随附文件 LICENSE_1_0.txt 或访问 https://boost.ac.cn/LICENSE_1_0.txt)
目录
编写 STL 迭代器、视图和容器出乎意料地困难。很多事情都可能微妙地出错。它也非常繁琐,这当然使其容易出错。
迭代器有许多 typedef 和操作,即使给定迭代器的所有操作都可以根据最多四个操作(通常只有三个)来实现。编写所有其他操作会产生非常相似的代码,这些代码难以审查,并且几乎都需要您为每个迭代器编写全覆盖测试。
编写像 std::ranges
中那样的视图类型也很费力,考虑到每个视图类型的大部分 API 都可以从 begin()
和 end()
派生出来。C++20 有一个模板可以完全做到这一点,std::ranges::view_interface
;Boost.STLInterfaces 提供了与 C++20 之前版本兼容的实现。
由于不同编译器实现其 C++20 视图适配器的 operator|
支持的方式不一致,因此尝试编写可跨多个 C++ 版本甚至跨在 C++20 模式下构建的多个编译器移植的视图适配器尤其棘手。Boost.STLInterfaces 提供了一个类型 boost::stl_interfaces::range_adaptor_closure
,它与 C++23 的 std::range_adaptor_closure
兼容,并且也适用于早期版本的 C++。Boost.STLInterfaces 还具有辅助模板,可以更轻松地编写带有 operator|
支持的视图适配器。
最令人畏惧的是编写满足标准中容器要求的类型或模板的任务。Boost.STLInterfaces 提供了另一个名为 sequence_container_interface
的模板,它大大减轻了实现和测试负担。
![]() |
注意 |
---|---|
提供了 C++20 版本的 |
这是一个库的迭代器部分的示例。假设我们想要创建一个随机访问迭代器,它表示由重复较短字符串构造的任意长度的字符串。我们称这个迭代器为 repeated_chars_iterator
。这是它的实际操作
repeated_chars_iterator first("foo", 3, 0); // 3 is the length of "foo", 0 is this iterator's position. repeated_chars_iterator last("foo", 3, 7); // Same as above, but now the iterator's position is 7. std::string result; std::copy(first, last, std::back_inserter(result)); assert(result == "foofoof");
标准库中没有任何东西可以让我们获得这种行为,所以我们必须自己编写它。这个库旨在将我们编写的内容从这样
struct repeated_chars_iterator { using value_type = char; using difference_type = std::ptrdiff_t; using pointer = char const *; using reference = char const; using iterator_category = std::random_access_iterator_tag; constexpr repeated_chars_iterator() noexcept : first_(nullptr), size_(0), n_(0) {} constexpr repeated_chars_iterator( char const * first, difference_type size, difference_type n) noexcept : first_(first), size_(size), n_(n) {} constexpr reference operator*() const noexcept { return first_[n_ % size_]; } constexpr value_type operator[](difference_type n) const noexcept { return first_[(n_ + n) % size_]; } constexpr repeated_chars_iterator & operator++() noexcept { ++n_; return *this; } constexpr repeated_chars_iterator operator++(int)noexcept { repeated_chars_iterator retval = *this; ++*this; return retval; } constexpr repeated_chars_iterator & operator+=(difference_type n) noexcept { n_ += n; return *this; } constexpr repeated_chars_iterator & operator--() noexcept { --n_; return *this; } constexpr repeated_chars_iterator operator--(int)noexcept { repeated_chars_iterator retval = *this; --*this; return retval; } constexpr repeated_chars_iterator & operator-=(difference_type n) noexcept { n_ -= n; return *this; } friend constexpr bool operator==( repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept { return lhs.first_ == rhs.first_ && lhs.n_ == rhs.n_; } friend constexpr bool operator!=( repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept { return !(lhs == rhs); } friend constexpr bool operator<( repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept { return lhs.first_ == rhs.first_ && lhs.n_ < rhs.n_; } friend constexpr bool operator<=( repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept { return lhs == rhs || lhs < rhs; } friend constexpr bool operator>( repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept { return rhs < lhs; } friend constexpr bool operator>=( repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept { return rhs <= lhs; } friend constexpr repeated_chars_iterator operator+(repeated_chars_iterator lhs, difference_type rhs) noexcept { return lhs += rhs; } friend constexpr repeated_chars_iterator operator+(difference_type lhs, repeated_chars_iterator rhs) noexcept { return rhs += lhs; } friend constexpr repeated_chars_iterator operator-(repeated_chars_iterator lhs, difference_type rhs) noexcept { return lhs -= rhs; } friend constexpr difference_type operator-( repeated_chars_iterator lhs, repeated_chars_iterator rhs) noexcept { return lhs.n_ - rhs.n_; } private: char const * first_; difference_type size_; difference_type n_; };
(那是很多代码!)变成这样
struct repeated_chars_iterator : boost::stl_interfaces::iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS repeated_chars_iterator, #endif std::random_access_iterator_tag, char, char> { constexpr repeated_chars_iterator() noexcept : first_(nullptr), size_(0), n_(0) {} constexpr repeated_chars_iterator( char const * first, difference_type size, difference_type n) noexcept : first_(first), size_(size), n_(n) {} constexpr char operator*() const noexcept { return first_[n_ % size_]; } constexpr repeated_chars_iterator & operator+=(std::ptrdiff_t i) noexcept { n_ += i; return *this; } constexpr auto operator-(repeated_chars_iterator other) const noexcept { return n_ - other.n_; } private: char const * first_; difference_type size_; difference_type n_; };
啊,这样好多了。repeated_chars_iterator
的这两个定义具有相同的语义和性能特征。只是编写第二个定义的代码要少得多,并且编写第二个定义对新手更友好。
![]() |
注意 |
---|---|
Boost.STLInterfaces 的 |