2017-02-03 17 views
2

は、私は、一般的なSTLコンテナを受け入れる機能を書面で自分を任務とし、この設計を思い付いた:奇妙な行動可変長引数テンプレート

template<template<class, class...> class C, 
     class... A, 
     class T = typename C<A...>::value_type> 
void wrong(std::vector<C<T, A...>>& indexes, std::vector<T>& resultSet) { 
    resultSet.push_back(indexes[0][0]); 
} 

露骨に間違っていた私の最初の試みであったが、それは私が働いていましたその、その後にスキップされ、私はコードレビュー中にミスを発見し、

template<template<class...> class C, 
     class... A, 
     class T = typename C<A...>::value_type> 
void correct(std::vector<C<A...>>& indexes, std::vector<T>& resultSet) { 
    resultSet.push_back(indexes[0][0]); 
} 

はのは、上記のコードは次のように使用されているとしましょう、より正確である次のことを書いた:

int main() 
{ 
    std::vector<int> v1 {1,2}, v2{3,4}; 
    std::vector<std::vector<int>> sets {v1, v2}; 
    std::vector<int> r; 

    wrong(sets, r); 
    std::cout << r.back() << std::endl; 
    r.clear(); 

    correct(sets, r); 
    std::cout << r.back() << std::endl; 

} 

私は同じを取得し(と意図した)行動のコンパイルが、私は「C」タイプは、引数がint型、int型、アロケータとして3種類がかかるので最初の間違った機能に障害が発生しているべきであると感じています。 2番目の動作は、テンプレートの理解に一致します。

質問は、上記のテンプレート控除で何が起こっているのですか?

+0

std :: vector > std :: vector

+0

がこの段階で失敗するはずです。GCCなどを使用する場合は、 'std :: cout << __PRETTY_FUNCTION__;テンプレートパラメータがどのように推測されるのかを確認します。 – DeiDei

答えて

1

C = std::vectorは、1つ以上のテンプレート引数(この場合はintAllocator)を取ることができるため、これを推論することができます。 Aは、ベクトルで使用されるアロケータでなければならないと推論します。最後にTintと推測されます(この場合はデフォルトの引数は使用しません)。我々はこれを書き出す場合は、私たちが見ることができる

void wrong(std::vector<std::vector<int, Allocator>>& indexes, std::vector<int>& resultSet); 

を得るだけでなく形成されており、私たちの引数を指定して呼び出すことができます。我々は、単に一つの他のパラメータ、A推測するにして残っているstd::vectorの最初のテンプレートパラメータを削除する場合ので

パラメータパックA

Allocatorの単一の値に推定されます。

+0

class T = typename C :: value_type 次に、Tは私のサンプルにAllocator型であるでしょう。 それは失敗するはずですが、少なくとも私はこれをあなたの推論では起こるだろうと思っていますが、確信が持てません。 –

+1

しかし、 'T'が導かれるので、デフォルトの引数が投げられます。 – user975989

+0

あなたは絶対に正しいです。 –