6

make_pair次の単純なクラスを検討してください。

template <class X, class Y>
struct Pair
{
    X x;
    Y y;
};

また、移動/コピーを表示する単純なクラスを作成します。

struct C
{
    C(int n_) : n(n_) {};
    C(const C& x) { n = x.n; std::cout << "Copy: " << n << std::endl; }
    C(C&& x)      { n = x.n; std::cout << "Move: " << n << std::endl; }
    int n;
};

次に、次を実行できます。

auto z1 = Pair<C, C>{C(1),C(2)};

出力Cはなく、移動もコピーもされません。

ただし、コンストラクターで型を指定する必要がありますPair。これらを推測したいとしましょう。次のようなことができます。

template <class X, class Y>
Pair<X, Y> make_pair(X&& x, Y&& y)
{
    return Pair<X, Y>{std::forward<X>(x), std::forward<Y>(y)};
}

そして、次のことができます。

auto z2 = make_pair(C(3),C(4));

しかし、これは次のように出力します:

Move: 3
Move: 4

ヒープ割り当てタイプであれば問題ありませんCが、スタック割り当てタイプの場合、移動は基本的にコピーです。

しかし、このマクロを定義しましょう:

#define MAKE_PAIR(x,y) decltype(make_pair(x,y)){x,y}

次に、次のことができます。

auto z3 = MAKE_PAIR(C(5),C(6));

そして、これは型推論を行い、移動を必要としません。しかし、マクロを作成する必要がありますが、これは少し面倒で、演算子を使用してこの種のことを行うのを妨げています。

次のことを行うソリューションはありますか。

(1) 型を推測する (2 と 3 のように)
(2) コピーや移動を必要としない (1 と 3 のように)
(3) マクロを必要としない (1 と 2 のように)

私が得ることができる最高のものは3分の2ですが、確かに3分の3は可能ですか? どうやら C++ はマクロから遠ざかりつつあるので、C++ が私が求めていた動作を得るためにマクロを使用することを強制するとは想像できません。

コードはこちらです。

4

2 に答える 2

1

どうやら C++ はマクロから遠ざかりつつあるので、C++ が私が求めていた動作を得るためにマクロを使用することを強制するとは想像できません。

あなたが求めている動作は、そもそも標準によって保証されていません。Elision は最適化です。実装には必要ありません。したがって、それらのどれもがあなたが望むことを保証するものではありませんが、明らかにそれらのいくつかは少なくともそれを可能にします.

フォワーディングは効果的に省略を不可能にします。その事実はどうしようもない。完全転送とは、参照と参照の崩壊がすべてです。省略は、最初の呼び出しサイトでは知ることができない値パラメーターを初期化する値に関するものです。

実際の状況では、これは問題になりません。実際に無視する価値のあるもののほとんどは、コピーにコストがかかるものです。int特に自明なクラスの場合、いくつかの やをコピーしてfloatsも、プロファイラーにブリップとして表示されることさえありません。ほとんどの場合、コピーにコストがかかるオブジェクトは、割り当てられたメモリなどの何らかのリソースを保持しているためです。そのため、コピーにコストがかかるほとんどのタイプも移動可能であり、したがって安価に移動できます。

いずれにせよ、はい、省略の可能性を持たせたい場合は、転送を使用できません。

于 2012-11-02T05:59:45.383 に答える
0

あなたの例では、タイプを一度指定する必要があります。タイプを複数回指定する必要がないようにすることが目標である場合は、次のようにすることができます。

auto z = Pair<C,C>{3,4};

これは、より複雑なコンストラクターがある場合でも機能することに注意してください。

struct C {
  C(int,int) { }
  C(int) { }
};

auto z = Pair<C,C>{{1,2},3};

コピーは必要ありません。

于 2012-11-02T06:00:09.910 に答える