関数のネストされた C++ テンプレートパラメータ 質問する

関数のネストされた C++ テンプレートパラメータ 質問する

C++ でテンプレート関数を作成したいのですが、その関数では、1 つのテンプレート パラメータが別のテンプレート パラメータのテンプレートになっています。意味がわからない場合は、次のコードを参照してください。このコードは、T 型でテンプレート化された std::vector を出力します。

template <typename T>
void print_vector(std::vector<T> &vec)
{
    for(auto v: vec)
        std::cout << v << " ";
    std::cout << std::endl;
}
...
std::vector<double> vec(5);
...
print_vector(vec);

この関数をさらに一般化したい。言語以外のコンテナvector。しかし、コンテナがT型でテンプレート化されるようにテンプレートパラメータを「ネスト」する方法がわかりません。次のことを試しましたが、成功しませんでした。

template <typename T, template <typename TT> V>
void print_container(V<T> &con)
{
    for(auto c: con)
        std::cout << c << " ";
    std::cout << std::endl;
}
...
std::vector<double> vec(5);
...
print_container(vec);

以前にもここで回答されているはずですが、回答を見つけるための検索用語が見つかりません。


@ForEveR さん、ありがとうございます。あなたの回答はまさにその通りです。私の質問に対するすべての回答で、「ストレージ」タイプ T をテンプレート化する必要はないと指摘されており、私が示した例には次のソリューションで十分です。

template <typename C>
void print_container(C &con)
{
    for(auto v: con)
        std::cout << v << " ";
    std::cout << std::endl;
}

残念ながら、この質問のきっかけとなった実際の使用例は、もう少し複雑でした。このルーチンは、行列とベクトルのクラスを含む次の線形代数の例のように、複数のコンテナーを使用します。

template <typename MATRIX, typename VECTOR>
void mat_vec_multiply(const MATRIX &A, const VECTOR &x, VECTOR &y)
{
    // Implement y = A*x;
}

MATRIX クラスと VECTOR クラスの両方を同じ基礎ストレージ クラス (つまり、、、など) にテンプレート化する必要があると仮定します。doubleテンプレートパラメータとして T を明示的に指定することで、これを強制できます。floatint

template < typename T,
           template<typename> class MATRIX,
           template<typename> class VECTOR>
void mat_vec_multiply(const MATRIX<T> &A, const VECTOR<T> &x, VECTOR<T> &y)
{
    // Implement y = A*x;
}

残念ながら、私はCUDAstd::is_sameコンパイラnvccはC++11の構文をサポートしていません(私の例では冗長性が少ないためC++11を使用しました)。そのため、とを使用することはできませんstatic_assertが、独自のものを作成することはできると思いますis_same(またはブースト) は簡単に実行できます。この場合、ストレージ クラスに共通のテンプレート パラメーターを適用するには、「ベスト プラクティス」とは何でしょうか。

ベストアンサー1

std::vector型とアロケータの2つのパラメータがあります。これを試してみてください

template <typename T, typename Alloc, template <typename, typename> class V>
void print_container(V<T, Alloc> &con)
{
}

print_container(vec);

vectorこれは、、などには機能しますがlist、、には機能しませんmapset

ただし、autoC++11 を使用すれば、次のことが可能になります。

template <typename T, template <typename, typename...> class V, typename... Args>
void print_container(V<T, Args...> &con)

または

template <template <typename, typename...> class V, typename... Args>
void print_container(V<Args...> &con)

そしてもちろん最も簡単な方法は、次のようにすることです

template<typename C>
void print_container(C& con)

おそらく推論のためのいくつかのチェックがあり、それはC実際にはコンテナです。

template<typename C>
auto print_container(C& con) -> decltype(con.begin(), void())

おすすめ記事