web-dev-qa-db-ja.com

std :: initializer_listコンストラクター

このようなコードでは:

#include <iostream> 
#include <initializer_list>
#include <string>

struct A 
{
  A() { std::cout << "2" << std::endl; }
  A(int a) { std::cout << "0" << std::endl; }
  A(std::initializer_list<std::string> s) { std::cout << "3" << std::endl; }
  A(std::initializer_list<int> l) { std::cout << "1" << std::endl; } 
};

int main() 
{ 
 A a1{{}}; 
} 

なぜコンストラクターのstd::initializer_list<int>仕様を呼び出すのですか?たとえば、コンストラクタをstd::initializer_list<double>で定義すると、あいまいなコンパイルエラーが発生します。そのような構成の規則は何ですか、そしてなぜそれはテンプレート引数として数を持つstd::initializer_listについてそれほど具体的ですか?

13
toozyfuzzy

クラスに初期化子リストコンストラクターがある場合、_{whatever goes here}_は引数として_{whatevergoeshere}_を現在のコンストラクターに渡すことを意味します(初期化子リストコンストラクターがない場合は、_whatever goes here_が引数として渡されます)。

それでは、設定を単純化して、他のコンストラクターを無視しましょう。コンパイラーはそれらを気にしないようです。

_void f(std::initializer_list<std::string> s);
void f(std::initializer_list<int> l); 
_

f({{}})には、このルールがあります

それ以外の場合、パラメータータイプがstd :: initializer_listであり、初期化子リストのすべての要素を暗黙的にXに変換できる場合、暗黙的な変換シーケンスは、リストの要素をXに変換するために必要な最悪の変換です。初期化子リストには要素、ID変換はありません。この変換は、初期化子リストコンストラクターの呼び出しのコンテキストでもユーザー定義の変換にすることができます。

ここでは、単一の要素_{}_があり、_std::string_を初期化するためにユーザー定義の変換が必要であり、intの変換(ID)は必要ありません。したがって、intが選択されます。

f({{{}}})の場合、要素は_{{}}_です。 intに変換できますか?ルールは

  • 初期化子リストに、それ自体が初期化子リストではない要素が1つある場合、暗黙の変換シーケンスは、要素をパラメーター型に変換するために必要なシーケンスです。
  • .。
  • 上に列挙したもの以外のすべての場合、変換は不可能です。

_std::string_に変換できますか?はい、_std::initializer_list<char> init_パラメーターを持つイニシャライザーリストコンストラクターがあるためです。したがって、今回は_std::string_を選択します。


A a3({})との違いは、このような場合、リストの初期化ではなく、_{}_引数を使用した「通常の」初期化です(外側の中括弧がないため、ネストが1つ少なくなることに注意してください)。ここでは、2つのf-関数が_{}_で呼び出されています。また、両方のリストに要素がないため、どちらの場合もID変換が行われるため、あいまいさが生じます。

この場合のコンパイラーは、f(int)も考慮し、他の2つの関数と連携します。ただし、intパラメータが_initializer_list_パラメータよりも悪いと宣言するタイブレーカーが適用されます。したがって、変換シーケンスの最良のグループには1つの候補ではなく、2つの候補が含まれるため、あいまいさの理由である半順序_{int} < {initializer_list<string>, initializer_list<int>}_があります。

{}からスカラー型(intdoublechar*など)への変換はID変換です。

{}からstd::initializer_listの特殊化以外のクラスタイプ(例:std::string)への変換はユーザー定義の変換です。

前者は後者を打ち負かします。

7
T.C.