の目的はstd::make_pair
何ですか?
なぜそうしないのstd::pair<int, char>(0, 'a')
ですか?
2つの方法に違いはありますか?
違いは、 withstd::pair
は両方の要素の型を指定する必要があるのに対し、std::make_pair
は渡された要素の型とペアを作成し、それを伝える必要がないことです。とにかく、それは私がさまざまなドキュメントから収集できたものです。
http://www.cplusplus.com/reference/std/utility/make_pair/からこの例を参照してください
pair <int,int> one;
pair <int,int> two;
one = make_pair (10,20);
two = make_pair (10.5,'A'); // ok: implicit conversion from pair<double,char>
それの暗黙の変換ボーナスは別として、make_pair を使用しなかった場合は、次のことを行う必要があります。
one = pair<int,int>(10,20)
あなたが1つに割り当てるたびに、それは時間の経過とともに迷惑になります...
@MSalters が上で回答したように、中かっこを使用して C++11 でこれを行うことができるようになりました (C++11 コンパイラでこれを確認しました)。
pair<int, int> p = {1, 2};
クラス テンプレート引数は、C++17 より前のコンストラクターから推論できませんでした
C++17 より前では、次のようなものを書くことはできませんでした。
std::pair p(1, 'a');
コンストラクターの引数からテンプレートの型を推測するため、次のように明示的に記述する必要がありました。
std::pair<int,char> p(1, 'a');
C++17 ではその構文が可能になるため、make_pair
冗長になります。
C++17 より前では、std::make_pair
あまり冗長でないコードを書くことができました。
MyLongClassName1 o1;
MyLongClassName2 o2;
auto p = std::make_pair(o1, o2);
より冗長な代わりに:
std::pair<MyLongClassName1,MyLongClassName2> p{o1, o2};
タイプを繰り返すため、非常に長くなる可能性があります。
make_pair
はコンストラクターではないため、型推論は C++17 より前のケースで機能します。
make_pair
基本的に次と同等です。
template<class T1, class T2>
std::pair<T1, T2> my_make_pair(T1 t1, T2 t2) {
return std::pair<T1, T2>(t1, t2);
}
inserter
vsにも同じ概念が適用されinsert_iterator
ます。
以下も参照してください。
最小限の例
物事をより具体的にするために、次の方法で問題を最小限に観察できます。
main.cpp
template <class MyType>
struct MyClass {
MyType i;
MyClass(MyType i) : i(i) {}
};
template<class MyType>
MyClass<MyType> make_my_class(MyType i) {
return MyClass<MyType>(i);
}
int main() {
MyClass<int> my_class(1);
}
それから:
g++-8 -Wall -Wextra -Wpedantic -std=c++17 main.cpp
うまくコンパイルされますが、次のようになります。
g++-8 -Wall -Wextra -Wpedantic -std=c++14 main.cpp
次のエラーで失敗します:
main.cpp: In function ‘int main()’:
main.cpp:13:13: error: missing template arguments before ‘my_class’
MyClass my_class(1);
^~~~~~~~
代わりに動作する必要があります:
MyClass<int> my_class(1);
またはヘルパー:
auto my_class = make_my_class(1);
コンストラクターの代わりに通常の関数を使用します。
の違いstd::reference_wrapper
This commentstd::make_pair
は、コンストラクターがアンラップしないのにアンラップすることに言及しているstd::reference_wrapper
ため、それが1つの違いです。TODO の例。
GCC 8.1.0、Ubuntu 16.04 でテスト済み。
指定された型引数でコンストラクターを使用することmake_pair
と明示的に呼び出すことに違いはありません。テンプレートメソッドには指定されたパラメーターに基づく型推定があるため、型が冗長な場合はより便利です。例えば、pair
std::make_pair
std::vector< std::pair< std::vector<int>, std::vector<int> > > vecOfPair;
std::vector<int> emptyV;
// shorter
vecOfPair.push_back(std::make_pair(emptyV, emptyV));
// longer
vecOfPair.push_back(std::pair< std::vector<int>, std::vector<int> >(emptyV, emptyV));
これは、C++ テンプレート プログラミングの一般的なイディオムであることに注意してください。これはオブジェクト ジェネレーターのイディオムとして知られています。詳細と適切な例については、こちらを参照してください。
編集コメントで誰かが提案したように(削除されたため)、以下は、リンクが壊れた場合に備えて、リンクからわずかに変更された抜粋です。
オブジェクト ジェネレーターを使用すると、オブジェクトの型を明示的に指定せずにオブジェクトを作成できます。これは、クラス テンプレートにはない関数テンプレートの便利なプロパティに基づいています。関数テンプレートの型パラメーターは、実際のパラメーターから自動的に推定されます。関数の実際のパラメーターに応じてテンプレートstd::make_pair
のインスタンスを返す簡単な例です。std::pair
std::make_pair
template <class T, class U>
std::pair <T, U>
make_pair(T t, U u)
{
return std::pair <T, U> (t,u);
}
make_pair は、直接コンストラクターに余分なコピーを作成します。単純な構文を提供するために、常にペアを型定義します。
これは違いを示しています (Rampal Chaudhary による例):
class Sample
{
static int _noOfObjects;
int _objectNo;
public:
Sample() :
_objectNo( _noOfObjects++ )
{
std::cout<<"Inside default constructor of object "<<_objectNo<<std::endl;
}
Sample( const Sample& sample) :
_objectNo( _noOfObjects++ )
{
std::cout<<"Inside copy constructor of object "<<_objectNo<<std::endl;
}
~Sample()
{
std::cout<<"Destroying object "<<_objectNo<<std::endl;
}
};
int Sample::_noOfObjects = 0;
int main(int argc, char* argv[])
{
Sample sample;
std::map<int,Sample> map;
map.insert( std::make_pair( 1, sample) );
//map.insert( std::pair<int,Sample>( 1, sample) );
return 0;
}