Reputation: 2097
In various situations I have a collection (e.g. vector) of objects that needs to be processed by a number of functions. Some of the functions need to modify the objects while others don't. The objects' classes may inherit from an abstract base class. Hence, I have something like this:
class A
{
public:
virtual void foo() const = 0;
virtual void bar() = 0;
/* ... */
};
void process_1(std::vector<std::reference_wrapper<A>> const &vec);
void process_2(std::vector<std::reference_wrapper<A const>> const &vec);
Obviously (?) I can't pass the same vector of std::reference_wrapper<A>
s to both process_1
and process_2
. Solutions I've considered so far include:
reinterpret_cast
on a reference to vec
T& get()
and T const & get() const
instead of T& get() const
const
const
in reference_wrapper
's argumentNone of these seems very elegant. Is there something else I could do?
Upvotes: 3
Views: 1432
Reputation:
Even lacking elegance, I would make a reference wrapper:
#include <functional>
template <typename T>
class ReferenceWrapper
{
public:
ReferenceWrapper(T& ref)
: m_ref(ref)
{}
ReferenceWrapper(const std::reference_wrapper<T>& ref)
: m_ref(ref)
{}
const T& get() const noexcept { return m_ref.get(); }
T& get() noexcept { return m_ref.get(); }
operator const T& () const noexcept { return m_ref.get(); }
operator T& () noexcept { return m_ref.get(); }
private:
std::reference_wrapper<T> m_ref;
};
It is a tiny class modeling the original requirements.
Upvotes: 1
Reputation: 275575
Range adapters.
A range adapter takes a range as input (a container is a range, as it has begin
and end
returning iterators), and returns a range with different properties.
You'd cast your reference wrappers to the const
variant when you dereference the iterator.
boost
has iterators that will do this for you (transform iterators), and tools to help write conforming iterators, but it can be done from scratch with some work.
A bit of extra work could even keep the typenames sane.
Upvotes: 3