В различных ситуациях у меня есть коллекция (например, вектор) объектов, которые должны быть обработаны рядом функций. Некоторые функции должны изменять объекты, а другие нет. Классы объектов могут наследоваться от абстрактного базового класса. Следовательно, у меня есть что-то вроде этого:
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);
Очевидно (?) Я не могу передать тот же вектор std::reference_wrapper<A>
с обоими process_1
а также process_2
, Решения, которые я рассмотрел до сих пор, включают:
reinterpret_cast
на ссылку на vec
T& get()
а также T const & get() const
вместо T& get() const
const
const
в reference_wrapper
аргументНичто из этого не кажется очень элегантным. Есть ли что-то еще, что я мог сделать?
Адаптеры дальности.
Адаптер диапазона принимает диапазон в качестве входных данных (контейнер является диапазоном, так как он имеет begin
а также end
возвращает итераторы) и возвращает диапазон с различными свойствами.
Вы бросили свои справочные обертки на const
Вариант, когда вы разыменовываете итератор.
boost
есть итераторы, которые сделают это за вас (преобразователи итераторов), и инструменты, помогающие писать соответствующие итераторы, но это можно сделать с нуля с некоторой работой.
Небольшая дополнительная работа могла бы даже сохранить разумные имена.
Даже не имея элегантности, я сделал бы справочную обертку:
#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;
};
Это крошечный класс, моделирующий исходные требования.