Search code examples
c++c++11reference-wrapper

Const correctness with reference_wrapper


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:

  • Using a C-style cast or reinterpret_cast on a reference to vec
  • Writing my own reference wrapper that has T& get() and T const & get() const instead of T& get() const
  • Refactoring with e.g. methods that take a wrapper instead of the vector
  • Having copies of the vector with and without const
  • Not using const in reference_wrapper's argument

None of these seems very elegant. Is there something else I could do?


Solution

  • 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.