Копировать/перемещать требования для типов ключей/значений в std:: map?

Этот код меня смущает:

struct foo {
  int i;

  foo(int j) : i(j) {}

  foo(const foo &) = delete;
  foo(foo &&) = delete;
  foo &operator=(const foo&) = delete;
  foo &operator=(foo&&) = delete;
};

bool operator<(const foo &f1, const foo &f2)
{
  return f1.i < f2.i;
}

int main(int argc, char **argv)
{
  std::map<foo,int> f;
  std::map<foo,int> f2 = f; //error (as expected)
  std::map<foo,int> f3 = std::move(f); //no error (why?)
  return 0;
}

Поскольку я не получаю ошибок там, кажется, что при перемещении карты не создается ключевой объект (даже для перемещения в него другого ключевого объекта).

Почему бы и нет? Могу ли я полагаться на это поведение в соответствии со стандартом С++ 11?

В более общем плане, какие требования к копированию/перемещению занимают место std::map на клавишах и типах значений и при каких условиях?

Ответ 1

Скопировать назначение одной карты в другую требует копирования каждого элемента. Поскольку вы не можете копировать элементы, вы не можете копировать-назначать карты.

Является ли фактический объект карты пустым во время выполнения, является несущественным, поскольку они являются чисто статическими соображениями, полностью определяемыми типами объектов.

(Мне нравится спрашивать, почему sin(0) требуется единица с плавающей точкой, когда результат является целым числом.)

Перемещение всей карты, с другой стороны, прекрасно, потому что контейнер имеет node и фактические значения не изменяются, а только узлы. Фактически, контейнеры, основанные на перемещении или перемещении, на основе node не требуют, чтобы элементы были подлежащими перепрограммированию или перемещению или присваиванию вообще.

(Это должно быть верно для всех контейнеров, которые управляют динамической памятью подходящим образом, например, через std::allocator<value_type>, но это, конечно, не соответствует действительности для std::array, и было бы интересно, будет или нет он будет придерживаться std::dynarray, и, как заметил Джонатан Вакли, если схема распределения не способна переместить узлы оптом.)

Ответ 2

Нет ошибки, потому что перемещено только map, а не элементы map. Только указатели на элементы назначаются