の目的はstd::make_pair
何ですか?
なぜしないのですstd::pair<int, char>(0, 'a')
か?
2つの方法に違いはありますか?
std::make_pair
冗長です。これについて詳しく説明する以下の回答があります。
の目的はstd::make_pair
何ですか?
なぜしないのですstd::pair<int, char>(0, 'a')
か?
2つの方法に違いはありますか?
std::make_pair
冗長です。これについて詳しく説明する以下の回答があります。
回答:
違いはstd::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つに割り当てるたびに、時間が経つと煩わしくなります...
one = {10, 20}
、チェックするのに便利なC ++ 11コンパイラはありません。
make_pair
、は、構造体、共用体、ラムダ、およびその他の不可解なものなど、名前のない型で動作することにも注意してください。
クラステンプレート引数は、C ++ 17より前のコンストラクターから推測できませんでした
C ++ 17以前は、次のようなものを書くことはできません。
std::pair 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の違い
このコメントは、コンストラクターがstd::make_pair
アンラップstd::reference_wrapper
しないのにアンラップすることを述べているので、それが1つの違いです。TODOの例。
GCC 8.1.0、Ubuntu 16.04でテスト済み。
std::make_pair
-C ++ 17で非推奨にならないのはなぜですか?
make_pair
参照ラッパーをアンラップするため、実際にはCTADとは異なります。
型引数を指定し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);
}
&&
はC ++ 11以降。
make_pairは、直接コンストラクター上に追加のコピーを作成します。私は常にペアをtypedefして、単純な構文を提供します。
これは違いを示しています(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;
}
std::move
内部insert
や周辺で同じ結果が得られsample
ます。変更std::map<int,Sample>
しstd::map<int,Sample const&>
て初めて、構築されたオブジェクトの数を減らし、すべてのコピーを(明らかに)削除するのは、コピーコンストラクターを削除したときだけです。これらの両方の変更を行った後の結果には、デフォルトのコンストラクターへの1回の呼び出しと、同じオブジェクトのデストラクターへの2回の呼び出しが含まれています。私は何かを逃しているに違いないと思います。(g ++ 5.4.1、c ++ 11)
emplace
のinsert
場合(そして、追加のインスタンスが必要ない場合)の代わりにお勧めします。私が専門知識を持っているとは言えないかもしれませんが、コピー/移動C ++ 11によって導入されたセマンティクスは、私を大きく助けてくれました。