#include <iostream>
#include <string>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <vector>
class Base{
public:
virtual ~Base() {}
};
class Derived: public Base { };
int main(){
int arr[10];
Derived d;
Base *p = &d;
std::map<std::type_index, std::string> proper_name = {
{typeid(int), "int"}, {typeid(double), "double"}, {typeid(float), "float"}, {typeid(char), "char"},
{typeid(Base), "Base"}, {typeid(Derived), "Derived"}, {typeid(std::string), "String"},
{typeid(int[10]), "Ten int Array"}, {typeid(p), "Base Pointer"}};
}
このリストの初期化で発生する暗黙の変換を理解しようとしています。13.3.1.7
N3337から:
非集約クラス型 T のオブジェクトがリスト初期化される (8.5.4) 場合、オーバーロードの解決は 2 つのフェーズでコンストラクターを選択します。
最初は、候補関数はクラス T の初期化子リスト コンストラクター (8.5.4) であり、引数リストは単一の引数としての初期化子リストで構成されます。
実行可能な初期化子リスト コンストラクターが見つからない場合、オーバーロードの解決が再度実行されます。ここで、候補関数はすべてクラス T のコンストラクターであり、引数リストは初期化子リストの要素で構成されます。
8.5.4
:
コンストラクターは、その最初のパラメーターが型であるか、ある type に対して
std::initializer_list<E>
cv 修飾されている可能性のある参照であり、他のパラメーターがないか、他のすべてのパラメーターがデフォルト引数を持っている場合、初期化子リスト コンストラクターです。std::initializer_list<E>
E
したがって、次のコンストラクタのリストは次のことをstd::map
示しています
map (initializer_list<value_type> il,
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type())
;
は候補関数でvalue_type
、この場合はpair<const type_index, std::string>
です。最後に から13.3.3.1.5
:
パラメーターの型が
std::initializer_list<X>
or の「配列X
」135 であり、初期化子リストのすべての要素を暗黙的に に変換できる場合X
、暗黙的な変換シーケンスは、リストの要素を に変換するために必要な最悪の変換X
です。
したがって、波括弧リストの要素が暗黙的に に変換される限り、これは有効な変換ですpair<const type_index, std::string>
。しかし、それらの要素は波括弧リストそのものでもあります。Pair
はイニシャライザ リスト コンストラクタを取りません。ここから、ブレース付き初期化リストからのコピー初期化は13.3.1.7
、オブジェクトを構築するために の 2 番目の部分を使用するようです。したがって、次のようになります。
pair<const type_index, std::string> p = {typeid(int), "int"}
になります:
pair<const type_index, std::string> p(typeid(int), "int")
しかし、これは暗黙の変換と見なされますか? 2引数のコンストラクターの使用を暗黙の変換と見なすにはどうすればよいですか? これに関する規格のコメントは何ですか?