2017-03-05 4 views
1

以下のコードでは、両方のバージョンのprintメソッドを使用して、最初の呼び出しがinitializer_listを持つ呼び出しに解決されます。 initializer_listで定義をコメントアウトすると、プログラムはシームレスにベクトルバージョンを使用します。最初のケースでは、コンパイラが不平を言うのを期待していました!コンパイラはvectorとinitializer_listのどちらを決定するのですか?

#include <iostream> 
#include <vector> 
using namespace std; 

void print(const vector<int>& v1){ 
     cout << "vector \n"; 
} 
void print(const initializer_list<int>& il) { 
     cout << "init list \n"; 
} 

int main() { 
     print({1,2,3,4,5}); 
     return 0; 
} 
+0

これは、C++で過負荷解決が機能する方法です。 – 101010

答えて

1

これは、overload resolutionがC++で動作する方法です。 printの両方のバージョンは、過負荷解決のために実行可能です。

  • print(const vector<int>& v1)呼び出し側で入力された初期化子リスト{1,2,3,4,5}std::vector<int>に暗黙的に変換されるため、オーバーロードの解決のための実行可能な機能です。
  • print(const initializer_list<int>& il)は、呼び出し元の入力タイプが完全に一致するため、オーバーロードの解決に使用可能な関数です。

両方の過負荷が発生した場合は、print(const initializer_list<int>& il)が最適な実行可能な機能として選択されます。これは完璧な一致であり、暗黙の変換よりもオーバーロードの分解能が高い優先順位です。

0

オーバーロードの分解能は、引数を変換シーケンスとしてパラメータ型に変換するために必要な操作を表現し、変換シーケンスをいくつかのルールに従ってランク付けすることによって機能します。

我々は参照を初期化しているので、[over.ics.ref]/2が適用される:

参照型のパラメータを引数発現に直接結合していない場合、変換シーケンスをするために必要なものです13.3.3.1に従って、引数表現を参照の基礎となる型に変換する。概念的には、この変換シーケンスは、引数式を使用して、潜在型の一時的なコピーを初期化することに対応しています。トップレベルのcv-qualificationの差異は、初期化自体に含まれ、変換を構成しません。

これは私たちがコード場合と同じ変換シーケンス規則を使用することができた:パラメータの代わりにconstの参照として非constオブジェクトと

void o_print(initializer_list<int> ol); 
void o_print(vector<int> o1); 

すなわち。今

  • [over.ics.list]/2によれば、std::initializer_list<int>intのブレースリストの変換は、恒等変換あります。 (リストメンバーがプロモーションやintへの変換を必要とするかどうかは分かりません)。

  • は[over.ics.list]/4によれば、非集約クラスにブレースリストの変換(ここでstd::vector<int>)はオーバーロード解決によってstd::vectorのコンストラクタを選択し、この配列はUSER-のように定義されます定義済み変換シーケンス

最後に、今すぐランキングルールを適用する準備が整いました。アイデンティティ変換はユーザ定義の変換シーケンスよりも高いランク付けされているので、initializer_list<int>バージョンが勝ちます。

NB。すべての参照はC++ 14です。

関連する問題