6

関数テンプレートのパラメータの型推定手順について質問があります。

次の例を見てください。

#include <vector>
#include <sstream>
#include <string>
#include <iterator>
#include <fstream>

int main()
{
    std::ifstream file("path/to/file");
    std::vector<int> vec(std::istream_iterator<int>{file},{}); // <- This part
    return 0;
}

私が物事を正しく理解していれば、2 番目のパラメーターはstd::istream_iterator、デフォルトのコンストラクターが呼び出される型であると推定されます。

適切なstd::vectorコンストラクターは次のように宣言されます。

template <class InputIterator>
         vector (InputIterator first, InputIterator last,
                 const allocator_type& alloc = allocator_type());

std::istream_iterator<int>2 番目のパラメータも同様に推定されるので、最初のパラメータの型が推定されるstd::istream_iterator<int>ため、統一された初期化セマンティクスを適用できます。私が知らないのは、型推論がどの順序で行われるかです。これに関する情報をいただければ幸いです。

前もって感謝します!

4

1 に答える 1

9

もっと簡単な例を使ってみましょう:

template<class T>
void foo(T, T);

foo(42, {});

関数呼び出しには 2 つの引数があります。

  • タイプの prvalue 式int(整数リテラル)
  • ブレース初期化リスト {}

後者の は式リスト{}の一部にすることができますが、それ自体はではありません。expression-listはinitializer-listとして定義されます。ブレース初期化リストには型がありません。

テンプレートの型推定は、各関数パラメーターに対して個別に行われます [temp.deduct.type]/2. [temp.deduct.call]/1 は、関数パラメーターの型推定について述べていますP

から参照と cv 修飾子を削除すると、いくつかのP 'に対してP' がP与えられ 、引数が初期化子リストである場合、代わりに初期化子リストの各要素に対して演繹が実行され、P'が関数テンプレートのパラメーターの型として、初期化子の要素が次のようになります。その引数。それ以外の場合、初期化子リストの引数により、パラメーターは非推定コンテキストと見なされます。[鉱山を強調]std::initializer_list<>

したがって、呼び出しfoo(42, {});では、Tは 2 番目の引数から推測されません{}。ただし、T最初の引数から推測できます。

T一般に、複数の関数パラメーターから推測できます。その場合、推定される型は [temp.deduct.type]/2 と正確に一致する必要があります。型が 1 つの関数パラメーターからのみ推定され、別の場所 (非推定コンテキストにある別の関数パラメーター、戻り値の型など) で使用されている場合、問題はありません。型推定は、テンプレート パラメータがどの関数パラメータからも推定できず、明示的に設定されていない場合などに失敗する可能性があります。

演繹後、Tに置き換えられint、次のような関数シグネチャが生成されます。

void foo<int>(int, int);

この関数は、 と の 2 つの引数で呼び出すことができ42ます{}。後者は、2 番目のパラメーターの値の初期化につながるコピー リストの初期化を実行します。

于 2014-06-05T12:31:32.333 に答える