|
Boost Users : |
Subject: Re: [Boost-users] Reverse for loop with boost::adaptors::reverse crashes
From: Filip KonviÄka (filip.konvicka_at_[hidden])
Date: 2014-11-28 04:03:06
> This works (albeit possibly with a performance penalty in the form of a
> double copy; I'm not sure if the compiler can be smart enough to elide
> that):
>
> template<typename T, typename R>
> std::vector<T> as_vector(const R& range)
> {
> return std::vector<T>(boost::begin(range), boost::end(range));
> }
>
> ...
>
> for (int i : as_vector<int>(boost::adapters::reverse(getv())))
>
Thanks, this might be helpful.
I am using the following when I write functions that return a range of
any_iterators to something that is a temporary vector:
namespace detail {
template<typename PBackupVector, typename I>
struct it_PXYZ_Backup2 : public I {
/// A shared pointer to the backup container.
/// The backup container is deleted with the last iterator to it.
PBackupVector pBK;
/// Construction - increment use count of the container,
/// and copy the real iterator.
it_PXYZ_Backup2(PBackupVector const& pBK, I const& it)
: I(it)
, pBK(pBK)
{}
};
}
/// Copies the container contents to a temporary vector and returns
/// iterator range over the copy.
/// The temporary vector is automatically removed when the last
/// iterator is destroyed.
template<typename it_PXYZ, typename C>
iterator_range<it_PXYZ>
iterators_from_copy(C const& container) {
typedef std::vector<typename C::value_type> BackupVector;
typedef shared_ptr<BackupVector> PBackupVector;
PBackupVector pBackupVector =
PBackupVector(new BackupVector(container.begin(), container.end()));
typedef detail::it_PXYZ_Backup2<
PBackupVector, typename BackupVector::const_iterator> it;
return boost::make_iterator_range(
it_PXYZ(it(pBackupVector, pBackupVector->begin())),
it_PXYZ(it(pBackupVector, pBackupVector->end())));
}
You can then e.g.
iterator_range<it_PXYZ> getFiltered(std::vector<PXYZ> const& all) {
std::vector<PXYZ> filtered;
std::copy_if(all.begin(), all.end(), filtered.end(), ....);
return iterators_from_copy<it_PXYZ>(filtered);
}
> It might be easier just to rewrite it like this though, which will
> satisfy the lifetime requirement while avoiding the possible performance
> penalty:
>
> auto v = getv();
> for (int i : boost::adapters::reverse(v)) {...}
That is what I would do at the moment.
By the way, I started a discussion on the topic at
comp.lang.c++.isocpp.general - "Range-based for loop temporaries
lifetime". There are some interesting comments on the subject there.
Cheers,
Filip
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net