C++11, const члены данных, std::insertter, copy

Вот простой пример класса Test

#include <algorithm>
#include <iterator>
#include <vector>

template <typename T>
struct MinMax { T min, max; };

template <typename T>
using TList = std::vector<T>;

template <typename T>
class Test
{
   private:
      const T a, b;         
      const MinMax <T> m;   
   public:
      Test() : a(0), m{ 0, 0 }, b(0.0) {};
   public:
      T getA() const { return a; }
      MinMax <T> & getMinMax() const { return m; }
      T getB() const { return b; }
      Test(const Test &t) : a(t.a), b(t.b), m(t.m ) {}
};

с постоянными данными членов. Вместо конструктора данные не изменяются. Я хотел бы скопировать вектор объектов Test в другой вектор, используя std::insertter. Я удивлен, что конструктор копирования не достаточно

int main()
{
   TList <Test <double> > t1;
   TList <Test <double> > t2;
   Test<double> t;
   t1.push_back(t);
   std::copy(t2.begin(), t2.end(), std::inserter(t1, t1.begin()));

   return 0;
}

и появляется следующая ошибка компилятора (VS2015):

Error   C2280   'Test<double> &Test<double>::operator =(const Test<double> &)': attempting to reference a deleted function  Const

Можно ли позволить элементам данных const и выполнить копирование другим способом (некоторые взломать:-))? Или оператор = должен быть определен, чтобы элементы данных не могли быть константными (невозможно присвоить объекту с константными элементами данных)?

Спасибо за вашу помощь.

1 ответ

Решение

Вставка в vector переназначает все элементы после вставленного элемента и назначает вставленный элемент освобожденному слоту.

Другими словами, вы не можете, потому что Стандарт требует, чтобы элементы стандартных контейнеров были Asssignable (иметь a = b определено), чтобы предложить полную функциональность.

Помимо очевидного решения написания собственного operator= Вы также можете добавить элементы с постоянными членами к vector толкая назад:

std::copy(t2.begin(), t2.end(), std::back_inserter(t1));

но это отчасти работает против Стандарта; push_back не требуется назначение, но другие функции могут.

Или вы можете использовать контейнер, который не требует присваивания для вставки, например:

template <typename T>
using TList = std::list<T>;

компенсируя все преимущества непрерывного локального кэша памяти vector,

В заключительной записке я стараюсь не объявлять данные членами моих структур const из-за таких проблем с универсальными контейнерами, которые требуют присваивания под капотом. Обратите внимание, что в вашем примере удаление const из частных пользователей оставило бы вас с достаточно хорошими полями только для чтения (которые могут быть доступны только через получателей извне).

Другие вопросы по тегам