Скажем, у меня есть Storage
некоторого Object
, который имеет метод, который агрегирует указатели на некоторые из Objects
в векторе. Вот так:
class Storage
{
public:
std::vector<Object*> aggregate_some_objects(); // non-const version
std::vector<const Object*> aggregate_some_objects() const; // const version
private:
std::unordered_map<size_t, Object> m_objects; // data is stored
// by-value in a non-vector container
}
Как правило, существует способ избежать копирования-вставки в реализации пар const + non-const, вызывая один из них внутри другого с помощью const_cast
. Здесь, однако, это невозможно, потому что возвращаемые типы методов различны.
Самый простой способ избежать копирования-вставки здесь - вызывать const
версию из версии не const
и использовать возвращенный std::vector<const T*>
для заполнения отдельного std::vector<T*>
. Однако это приведет к по меньшей мере двум распределениям кучи (по одному для каждого вектора). Я хотел бы избежать выделения, связанные со вторым вектором.
Интересно, есть ли способ написать что-то вроде
template <typename T>
std::vector<T*> remove_const_from_vector_of_ptrs(std::vector<const T*>&& input)
{
std::vector<T*> ret;
// do some magic stuff here that does not involve
// more memory allocations
return ret;
}
Таким образом, позволяя писать
std::vector<const Object*> Storage::aggregate_some_objects() const
{
// non-trivial implementation
}
std::vector<Object*> Storage::aggregate_some_objects()
{
auto objects = const_cast<const Storage*>(this)->aggregate_some_objects();
return remove_const_from_vector_of_ptrs(std::move(objects));
}
В std::vector
(например, std::unique_ptr
) не существует метода "release", который позволяет переносить владение памятью - и по очень веской причине, поэтому я ожидаю, что это невозможно.
Я также понимаю, что если бы это было возможно, это была бы опасная операция, которую следует избегать вообще, как const_cast
. Но осторожное использование в таких случаях кажется более полезным, чем копирование.
Изменить: добавлены разъяснения к тому, что я подразумеваю под "дополнительными" распределениями и изменил Storage::aggregate_objects()
на Storage::aggregate_some_objects()
, чтобы лучше указать, что реализация этих методов более сложна, чем на основе диапазона цикл - отсюда желание избежать копирования вставки реализации.