2017-08-28 4 views
6

私は最近、C++プロジェクトに取り組んでいましたが、私が完全に理解できない文字列コンストラクタを使って端をつきました。関連するコードは以下の通りである(you can run here):文字列を1文字に初期化するこのコードは、なぜinitializer_listコンストラクタを呼び出しますか?

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

int main() { 
    string directParens(1, '*'); 
    string directBraces{1, '*'}; 
    string indirectBraces = {1, '*'}; 

    cout << directParens.size() << endl; // 1 
    cout << directBraces.size() << endl; // 2 
    cout << indirectBraces.size() << endl; // 2 
    return 0; 
} 

ストリングのブレース初期化バージョンはその中に2つの文字を有する結局、星続く数値1と、すなわち、char

文字列の中括弧で初期化されたバージョンが、サイズと文字を取り入れたコンストラクタではなく、initializer_listコンストラクタを呼び出す理由がわかりません。 initializer_listコンストラクタは、この署名を有する:stringbasic_stringチャーの別名であることを考慮

basic_string(std::initializer_list<CharT> init, 
      const Allocator& alloc = Allocator()); 

、特定の署名タイプintの要素の両方を含む初期{1, '*'}が、どのように

string(std::initializer_list<char> init, 
     const Allocator& alloc = Allocator()); 

であろうとこのコンストラクタに一致するcharタイプの?私はstd::initializer_listのすべてのリテラルが同じタイプでなければならないという印象を受けました - それは間違っていますか?

+1

注:コンバージョン[変換後の結果がターゲットタイプに適合する定数式の場合]は例外です(https://stackoverflow.com/a/26974911/1708801) –

答えて

15

このコンストラクタに一致するint型とchar型の両方の要素を含む初期化子{1、 '*'}はどうですか?

リテラル1と文字'*'の両方が縮小変換を使用せずにcharに変換可能であるため。したがって、彼らはinitializer_list<char>コンストラクタを呼び出す資格があります。そしてinitializer_listコンストラクタ常には、リストの初期化を使用するときに優先されます。パラメータからinitializer_listコンストラクタを呼び出すことができる場合は、それが実行されます。

要素コンテナのであることをあなたは、リスト内の要素を意図していない限りコンテナとブレース-INIT-リストを使用しないでください。それらをコンストラクターパラメーターとする場合は、コンストラクターを使用します。

+0

Ah、gotcha。したがって、変換を絞り込まずにすべての要素を基になる型に変換できる場合、中括弧の初期化子はinitializer_listとして解釈されます。これを確認するには、{3,3.0}をinitializer_list として解釈できますが、initializer_list ではなく、そして、{INT_MAX、 '*'}はinitializer_list ですか? – templatetypedef

+0

@templatetypedef: 'INT_MAX'はナローイング変換なしで' char'に変換できないので、 '{INT_MAX、 '*'}'の例*は 'initializer_list 'になりません。しかしそうでなければ、あなたは正しいです。 –

+0

ああ、狭い変換が*値ではなく*タイプ*に適用されたと思った。ありがとう! – templatetypedef

関連する問題