私の理解では、 std::make_pair
と std::make_Tuple
が存在する唯一の理由は、型が自動的に推定されるため、自分で型を記述する必要がないためです。 C++ 1zでは、 クラステンプレートのテンプレート引数の推定 があります。これにより、簡単に記述できます。
std::pair p(1, 2.5); // C++1z
の代わりに
auto p = std::make_pair(1, 2.5); // C++11/14
std::Tuple
の状況は類似しています。これにより、次の質問が発生します。C++ 1zでは、std::make_pair
およびstd::make_Tuple
のコンストラクターを使用する代わりに、std::pair
およびstd::Tuple
を使用することが有益な状況がありますか?
純粋なC++ 1zコード(つまり、C++ 14との下位互換性は不要)を検討し、誰もがこのC++ 1z機能に精通していると想定してください。
C++ 1zでは、_
std::make_pair
_と_std::make_Tuple
_のコンストラクターを使用する代わりに、_std::pair
_と_std::Tuple
_を使用することが有益な状況はありますか?
すべてのルールには常に楽しい例外があります。 _std::reference_wrapper
_に何をしたいですか?
_int i = 42;
auto r = std::ref(i);
pair p(i, r); // std::pair<int, std::reference_wrapper<int> >
auto q = std::make_pair(i,r); // std::pair<int, int&>
_
後者が必要な場合は、_std::make_pair
_が必要です。
別の状況はジェネリックコードで発生しました。タプルに変換したいテンプレートパラメータパックがあるとしましょう。これを記述しますか?
_template <typename... Ts>
auto foo(Ts... ts) {
return std::Tuple(ts...);
}
_
今、そのコードの意図はおそらくそれから_std::Tuple<Ts...>
_を取得することですが、それは必然的に何が起こるかではありません。 _Ts...
_に依存します:
Ts...
_がそれ自体がTuple
である単一のオブジェクトである場合、そのコピーを取得します。つまり、foo(std::Tuple{1})
は、_Tuple<int>
_ではなく_Tuple<Tuple<int>>
_を返します。Ts...
_がpair
である単一のオブジェクトである場合、それらの要素のTuple
を取得します。つまり、foo(std::pair{1, 2})
は、_Tuple<int, int>
_ではなく_Tuple<pair<int, int>>
_を返します。ジェネリックコードでは、Tuple
のようなタイプにCTADを使用することは避けます。これは、何を取得するかが明確にならないためです。 _make_Tuple
_にはこの問題はありません。 make_Tuple(tuple{1})
は_Tuple<Tuple<int>>
_であり、make_Tuple(pair{1, 2})
は_Tuple<pair<int, int>>
_です。
さらに、_std::make_pair
_は関数テンプレートであるため、何かを実行したい別の関数テンプレートにそれを渡すことができます。
_foo(std::make_pair<int, int>);
_
これはあまり便利ではないようですが、誰かが問題を解決するためにそれを使用しています-そしてあなたはそこに_std::pair
_を渡すことはできません。