有没有一种方法可以使用基于范围的迭代器来迭代对指针列表值的引用?
Is there a way to use a range-based iterator to iterate over references to the values of a list of pointers?
因此,如果我有以下向量,其中包含多个指向整数的指针:
std::vector<MyClass*> list;
我可以稍后使用类似的东西迭代它吗:
for (auto & (*item) : list)
{
item.member = something; //Goal is to require no dereferencing here
}
使用对列表内容值的引用比使用指向它们的指针要方便一些。
不,你不能。但你为什么要这么做?
for (auto pitem : list)
{
auto& item = *pitem;
item.member = something; // no dereferencing here
}
除非你愿意编写像这样乏味的代码:
template<class TPointer>
class Adaptor
{
struct Iterator
{
TPointer* _p;
Iterator(TPointer* p) : _p(p) {}
typename std::remove_pointer<TPointer>::type& operator*() { return **_p; }
Iterator& operator++() { ++_p; return *this; }
friend Iterator operator+(const Iterator& lhs, size_t s) { return lhs._p + s; }
friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs._p != rhs._p; }
};
std::vector<TPointer>& _v;
public:
Adaptor(std::vector<TPointer>& v) : _v(v) {}
Iterator begin() { return &_v[0]; }
Iterator end() { return begin() + _v.size(); }
};
才可以写:
struct SomeData { int n; } s1{2}, s2{4};
std::vector<SomeData*> data{&s1, &s2};
for (auto& item : Adaptor{data}) {
std::cout << item.n << "\n";
}
Boost 对此有一个范围适配器:http://www.boost.org/doc/libs/1_66_0/libs/range/doc/html/range/reference/adaptors/reference/indirected.html
for (auto& item : list | boost::adaptors::indirected) {
// do whatever with your reference
}
另一种选择是迭代器适配器,在这种情况下更冗长:http://www.boost.org/doc/libs/1_66_0/libs/iterator/doc/indirect_iterator.html
auto beg = boost::make_indirect_iterator(std::begin(list));
auto end = boost::make_indirect_iterator(std::end(list));
for (auto& item : boost::make_iterator_range(beg, end)) {
// do whatever with your reference
}
另一个使用嵌套 lambda 的变体。
std::for_each(std::begin(list), std::end(list), [] (auto p) {[item = *p] {
item.member = something;
}();});
因此,如果我有以下向量,其中包含多个指向整数的指针:
std::vector<MyClass*> list;
我可以稍后使用类似的东西迭代它吗:
for (auto & (*item) : list)
{
item.member = something; //Goal is to require no dereferencing here
}
使用对列表内容值的引用比使用指向它们的指针要方便一些。
不,你不能。但你为什么要这么做?
for (auto pitem : list)
{
auto& item = *pitem;
item.member = something; // no dereferencing here
}
除非你愿意编写像这样乏味的代码:
template<class TPointer>
class Adaptor
{
struct Iterator
{
TPointer* _p;
Iterator(TPointer* p) : _p(p) {}
typename std::remove_pointer<TPointer>::type& operator*() { return **_p; }
Iterator& operator++() { ++_p; return *this; }
friend Iterator operator+(const Iterator& lhs, size_t s) { return lhs._p + s; }
friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs._p != rhs._p; }
};
std::vector<TPointer>& _v;
public:
Adaptor(std::vector<TPointer>& v) : _v(v) {}
Iterator begin() { return &_v[0]; }
Iterator end() { return begin() + _v.size(); }
};
才可以写:
struct SomeData { int n; } s1{2}, s2{4};
std::vector<SomeData*> data{&s1, &s2};
for (auto& item : Adaptor{data}) {
std::cout << item.n << "\n";
}
Boost 对此有一个范围适配器:http://www.boost.org/doc/libs/1_66_0/libs/range/doc/html/range/reference/adaptors/reference/indirected.html
for (auto& item : list | boost::adaptors::indirected) {
// do whatever with your reference
}
另一种选择是迭代器适配器,在这种情况下更冗长:http://www.boost.org/doc/libs/1_66_0/libs/iterator/doc/indirect_iterator.html
auto beg = boost::make_indirect_iterator(std::begin(list));
auto end = boost::make_indirect_iterator(std::end(list));
for (auto& item : boost::make_iterator_range(beg, end)) {
// do whatever with your reference
}
另一个使用嵌套 lambda 的变体。
std::for_each(std::begin(list), std::end(list), [] (auto p) {[item = *p] {
item.member = something;
}();});