Подтвердить что ты не робот

С++ 11 use-case для кусочной_конструкции пары и кортежа?

В N3059 я нашел описание кусочной конструкции пар (и кортежей) (и он находится в новом стандарте).

Но я не вижу, когда я должен его использовать. Я нашел обсуждения об элементах emplace и non-copyable, но когда я попробовал это, я не смог создать случай, когда мне нужно piecewiese_construct или вы могли бы увидеть преимущество производительности.

Пример. Я думал, что мне нужен класс, который не копируется, но movebale (требуется для пересылки):

struct NoCopy {
  NoCopy(int, int) {};
  NoCopy(const NoCopy&) = delete; // no copy
  NoCopy& operator=(const NoCopy&) = delete; // no assign
  NoCopy(NoCopy&&) {}; // please move
  NoCopy& operator=(NoCopy&&) {}; // please move-assign
};

Затем я отчасти ожидал, что стандартная пара-конструкция завершится неудачно:

pair<NoCopy,NoCopy> x{ NoCopy{1,2}, NoCopy{2,3} }; // fine!

но это не так. На самом деле, это то, чего я ожидал в любом случае, потому что "перемещение вокруг", а не копирование его повсюду в stdlib, должно быть.

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

pair<NoCopy,NoCopy> y(
    piecewise_construct,
    forward_as_tuple(1,2),
    forward_as_tuple(2,3)
); // also fine
  • Итак, что такое usecase?
  • Как и когда использовать piecewise_construct?
4b9b3361

Ответ 1

Не все типы могут перемещаться более эффективно, чем скопировать, и для некоторых типов может иметь смысл даже явно отключить как копирование, так и перемещение. Рассмотрим std::array<int, BIGNUM> как пример первого типа типа.

Точка с функциями emplace и piecewise_construct заключается в том, что такой класс можно построить на месте, без необходимости создавать временные экземпляры для перемещения или копирования.

struct big {
    int data[100];
    big(int first, int second) : data{first, second} {
        // the rest of the array is presumably filled somehow as well
    }
};

std::pair<big, big> pair(piecewise_construct, {1,2}, {3,4});

Сравните приведенное выше с pair(big(1,2), big(3,4)), где должны быть созданы два временных объекта big, а затем скопированы - и перемещение вообще не помогает! Аналогично:

std::vector<big> vec;
vec.emplace_back(1,2);

Основной прецедент для кусочного построения пары - это размещение элементов в map или unordered_map:

std::map<int, big> map;
map.emplace(std::piecewise_construct, /*key*/1, /*value*/{2,3});