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 を明示的に指定することで、これを強制できます。float
int
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
、、には機能しませんmap
。set
ただし、auto
C++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())