Here, Is x
a std::vector<int>
or a std::vector<std::vector<int>>
?
その他の質問には他の回答がありますが、もう少し詳しく説明したいと思います。クラステンプレートの引数の控除を実行するときは、コンストラクタからsynthesize a bunch of function templates、次にdeduction guidesからいくつかを取得し、オーバーロード解決を実行して正しいテンプレートパラメータを決定します。
std::vector<T,A>
にはかなりのコンストラクタがありますが、そのほとんどにはT
は記載されていません。これはT
を推測できないコンテキストにするため、このオーバーロードで実行可能なオプションではありません。それらがある
template <class InputIt>
vector<typename std::iterator_traits<InputIt>::value_type> __f(InputIt, InputIt);
:アロケータをドロップすることで、私も簡素化しますまた、その後
template <class T> vector<T> __f(size_t, T const&); // #2
template <class T> vector<T> __f(vector<T> const&); // #5
template <class T> vector<T> __f(vector<T>&&); // #6, NB this is an rvalue ref
template <class T> vector<T> __f(initializer_list<T>); // #8
そしてこのdeduction guide、:我々は場合にのみ実行可能かもしれないものを使用するように設定を事前にプルーン私たちの5人の候補者は、[dcl.init]のように、__f({v.begin(), v.end()})
経由のコールをオーバーロードしています。これはリストの初期化であるため、start with the initializer_list
candidatesが存在しない場合にのみ、他の候補に進む。この場合、実行可能な候補(#8)はinitializer_list
なので、他の候補も考慮せずに選択します。その候補はstd::vector<int>::iterator
としてT
推測するので、私たちはその後、std::vector<std::vector<int>::iterator>
リスト初期化2回の反復子とのコンストラクタを選択するために、オーバーロードの解決のプロセスを再起動します。
これはおそらく望ましい結果ではありません - 私たちは、おそらくvector<int>
を望んでいました。そこに解決策は単純です:()
の使用:
今
std::vector x(v.begin(), v.end()); // uses explicit deduction guide
をinitializer_list
候補者が実行可能な候補ではないので、我々はリストの初期化を行っていません。結果として、控除ガイド(唯一の実行可能な候補)を介してvector<int>
を推論し、そのイテレータ対のコンストラクタを呼び出すことになります。これには実際にコメントを修正することの副次的な利点があります。
これは{}
を初期化する()
で初期化するよりも乱暴に異なる何かをする多くの場所の一つです。いくつかは、{}
が均一な初期化であると主張しています。私の経験則:具体的には{}
を使用してください。意識的には、{}
が提供する動作が必要です。それ以外の場合は()
です。
'X'は、おそらく 'のstd ::ベクトル<はstd ::ベクトル ::イテレータ>'です。 –
見るためのxに値を追加してください:[デモ](http://coliru.stacked-crooked.com/a/640910c60c5735c1)ので 'のstd ::ベクトル<はstd ::ベクトル ::イテレータ>'。 –
Jarod42
一般的に控除ガイドは何ですか?そうでない場合は、[this](http://en.cppreference.com/w/cpp/language/class_template_argument_deduction#User-defined_deduction_guides)が役立つ可能性があります。 – HolyBlackCat