c++ - boost::iterator_adaptor的遍历类别是由适配迭代器的类别决定的吗?

标签 c++ boost iterator

我的继承自 boost::iterator_adaptor 的类有如下代码

private:

using is_bidirectional = std::is_convertible<
  iterator_category, std::bidirectional_iterator_tag>;

typename std::enable_if<is_bidirectional::value>::type
decrement() { ... }

我想知道 enable_if 部分是否多余。如所写,如果适配迭代器不是双向的,则不会启用 decrement() 重载。但是我不知道 boost::iterator_adaptor 是否已经使用了 SFINAE这样我就不需要关心私有(private)重载中的遍历类别。代码编译并工作得很好。我只是问 enable_if 部分t 是否有用,或者它是否多余。

最佳答案

是的。

事实上,默认情况下,适配器确实反射(reflect)了基本迭代器的类别。

这是一个有效的综合测试:

Live On Coliru

#include <boost/iterator_adaptors.hpp>

template <typename BaseIterator>
struct Adapt : boost::iterator_adaptor<Adapt<BaseIterator>, BaseIterator> {
    using base = boost::iterator_adaptor<Adapt<BaseIterator>, BaseIterator>;
    using base::base;
    using base::operator=;
};

#include <iostream>
#include <iterator>
#include <typeinfo>

template <typename It>
std::string cat(It const&) {
    return typeid(typename std::iterator_traits<It>::iterator_category).name();
}

template <typename It, typename OutIt>
void test(std::string caption, It f, It l, OutIt out) {
    Adapt<It> af{f}, al{l};

    std::cout << caption << ", adapts to " << cat(af) << "\t";
    std::copy(af, al, out);
    std::cout << "\n";
}

template <typename Container, typename OutIt>
void test(std::string caption, Container const& c, OutIt out) {
    using BaseIterator = typename Container::const_iterator;
    Adapt<BaseIterator> f{c.begin()}, l{c.end()};

    test(caption, f, l, out);
}

#include <vector>
#include <forward_list>
#include <list>
#include <sstream>

int main() {
    using V = std::vector<int>;
    using L = std::list<int>;
    using FL = std::forward_list<int>;
    using II = std::istream_iterator<int>;
    using OI = std::ostream_iterator<int>;

    static_assert(std::is_same<std::random_access_iterator_tag, std::iterator_traits<V::iterator>::iterator_category>{}, "");
    static_assert(std::is_same<std::bidirectional_iterator_tag, std::iterator_traits<L::iterator>::iterator_category>{}, "");
    static_assert(std::is_same<std::forward_iterator_tag, std::iterator_traits<FL::iterator>::iterator_category>{}, "");
    static_assert(std::is_same<std::input_iterator_tag, std::iterator_traits<II>::iterator_category>{}, "");
    static_assert(std::is_same<std::output_iterator_tag, std::iterator_traits<OI>::iterator_category>{}, "");

    OI out(std::cout, " ");
    test("vector      ", V  { 1,2,3 }, out);
    test("list        ", L  { 4,5,6 }, out);
    test("forward_list", FL { 7,8,9 }, out);
    {
        std::istringstream iss("10 11 12");
        II f(iss), l;
        test("stream input", f, l, out);
    }
}

哪个打印¹

vector      , adapts to std::random_access_iterator_tag 1 2 3 
list        , adapts to std::bidirectional_iterator_tag 4 5 6 
forward_list, adapts to std::forward_iterator_tag   7 8 9 
stream input, adapts to std::input_iterator_tag 10 11 12 

¹ 通过 c++filt -t 过滤输出以获得更漂亮的类型信息

关于c++ - boost::iterator_adaptor的遍历类别是由适配迭代器的类别决定的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47332365/

相关文章:

C++ 模板和 STL vector 问题

java - 使用迭代器创建系列

c++ - 如何获得表格的大小

c++ - 为非静态引用成员类写入 `operator=`

c++ - Boost、异常、线程和异步,我该如何处理?

c++ - 不能在构造函数中使用 boost.asio 解析器

c++ - 有没有办法在 Visual Studio 中列出库依赖项?

C++ 嵌套类前向声明​​错误

c++ - 如果其他人正在等待,是否有标准的 STL 或 Qt 方法来产生互斥量,否则保留它?

c++ - 清理双向迭代器代码