C ++ 11 сценарий использования для кусочно-структурной пары и кортежа? - PullRequest
32 голосов
/ 28 мая 2011

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

Но я не вижу, когда мне следует это использовать. Я нашел обсуждения о emplace и не копируемых объектах, но когда я попробовал это, я не смог создать случай, когда мне понадобится 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?

1 Ответ

33 голосов
/ 28 мая 2011

Не все типы можно перемещать более эффективно, чем копировать, и для некоторых типов может иметь смысл даже явно отключить как копирование, так и перемещение. Рассмотрим 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});
...