返回迭代器以增强适配器转换的容器

时间:2017-07-08 19:47:42

标签: c++ c++11 boost

我想向一个类的用户提供迭代成员容器的可能性,但是应用了一个转换元素。 Boost适配器似乎非常适合转换容器,但我不知道怎么可能将它应用到我的用例中。

该函数返回一个包含开始和结束迭代器的IterPair模板,它在没有转换的情况下工作。但是,通过转换,我返回一对局部变量的迭代器。 由于它没有默认的构造函数,因此无法使转换后的容器成为成员。

class A
{
public:
    IterPair get_elems()
    {
          auto tr_vect =  vect_ | boost::adaptors::transformed(std::mem_fn(&std::string::c_str));
          return {std::begin(tr_vect), std::end(tr_vect)};
    }
private:
    std::vector<std::string> vect_;
}

2 个答案:

答案 0 :(得分:0)

我只是返回范围并将其留给用户调用开始/结束(或使用范围,如下例所示):

#include <boost/range/adaptor/transformed.hpp>

#include <cstring>
#include <initializer_list>
#include <iostream>
#include <string>
#include <vector>

class A {
public:
    A(std::initializer_list<std::string> xs) : vect_{std::move(xs)} {}

    // auto return type requires c++14
    auto get_elems() const {
        return vect_ |
               boost::adaptors::transformed(std::mem_fn(&std::string::c_str));
    }

private:
    std::vector<std::string> vect_;
};

int main(int argc, char** argv) {
    A a{"a", "ab", "abc"};
    auto xs = a.get_elems();
    for (const auto& x : xs) {
        std::cout << std::strlen(x) << "\n";
    }
    return 0;
}

live example

答案 1 :(得分:0)

我认为你可能正在接近这个错误...而不是做你写的东西,我会提供以下方法,这真的是太多的代码,在快速的帖子中充实:

template <typename CONTAINER, // your underlying container
          typename TRANSFORM> // functor for your transform
class transform_adaptor
{
    template <typename IT = typename CONTAINER::iterator>
    class proxy_iterator : private TRANSFORM {
        // standard iterator typedefs, sourced from CONTAINER::iterator

        typedef IT underlying_iterator;
        underlying_iterator i;
     public:
        auto operator * () const -> decltype(TRANSFORM{}(*i))
        {
            return this->operator () (*i);
        }
        // Other proxy functions for the underlying iterator,
        // i.e. operator++, etc
    }

    CONTAINER * cptr;
 public:
    typedef proxy_iterator iterator;
    typedef proxy_iterator const_iterator;
    // necessary value_type, iterator, allocator, etc adaptors here

    iterator begin() { return proxy_iterator(cptr->begin()); }
    iterator end() { return proxy_iterator(cptr->end()); }
};

我很遗憾没有勾勒出这个骨头,但事实证明它的代码比我现在编译和测试的代码要多得多......

这个想法是你创建一个包装器容器类,它包含底层容器的迭代器代理以及底层容器的引用(指针)。当代理迭代器被解除引用时,使用它的运算符*,它将转换应用于基础容器元素并返回其结果。

如果这不足,那就是它打破了某些操作的STL API,正如std::vector<bool>打破了一些东西 - 你不能从proxy_iterator句柄将元素分配回容器而不需要更多的hackery和保证您可以将传输的结果类型反向映射回原始数据域(即,您的变换是1到1,或双射)。因此,某些操作(如std :: sort)将在您的代理容器上失败,但如果您需要使用const容器在两个不同的api之间移动数据,它肯定是数据转换的一个很好的选择。