web-dev-qa-db-ja.com

ペアとタプルのpiecewise_constructのC ++ 11ユースケース?

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
  • では、ユースケースとは何ですか?
  • いつどのようにpiecewise_constructを使用しますか?
37
towi

すべてのタイプをコピーよりも効率的に移動できるわけではありません。一部のタイプでは、コピーと移動の両方を明示的に無効にすることも意味があります。前者の種類のタイプの例として、_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))と比較してください。ここでは、2つの一時的な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});
_
38
JohannesD