返回迭代器来提升适配器
我想向类的用户提供遍历成员容器的可能性,但是会对元素应用一个变换。 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_;
}
我认为你可能会错误地处理这个问题......而不是写你写的东西,我会提供以下方法,这是一个真正太多的代码,需要在快速文章中完成:
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之间移动数据,它肯定是数据转换的一个好选择。
我只是返回范围,并保留给用户以调用begin / end(或者使用范围如下例所示):
#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;
}
现场示例
链接地址: http://www.djcxy.com/p/47361.html