I want to have a templated function in C++, where one template parameter is itself a template of another template parameter. If that doesn't make any sense, take the following code that prints a std::vector that is templated on type T
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);
I want to further generalize this function for STL containers other than vector
. But I don't know how to "nest" the template parameters such that the container is templated on type T. I have tried the following with no success
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);
I am sure this has been answered here before, but I can't find the search terms to find the answer.
Thanks @ForEveR. Your response was right on the money! All of the responses to my question observed that there is no need have the "storage" type T templated, with the following solution being adequate for the example I gave:
template <typename C> void print_container(C &con) { for(auto v: con) std::cout << v << " "; std::cout << std::endl; }
Unfortunately, the actual use case that motivated the question was a little bit more complicated. The routine takes multiple containers, like this linear algebra example with a matrix and vector class:
template <typename MATRIX, typename VECTOR> void mat_vec_multiply(const MATRIX &A, const VECTOR &x, VECTOR &y) { // Implement y = A*x; }
Assume that both the MATRIX and VECTOR classes have to be templated on the same underlying storage class (i.e., double
, float
, int
, etc.). The idea is that by explicitly specifying T as a template parameter, we can enforce this:
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; }
Unfortunately, I am using the CUDA compiler nvcc, which doesn't have any support for C++11 constructs (I just used C++11 in my example because it is less verbose). So I can't use std::is_same
and static_assert
, though I suppose I could roll my own is_same
(or use Boost) easily enough. What is the "best practice" in this case, where I want to enforce the common template parameter for the storage classes?
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
Template non-type arguments in C++It is also possible to use non-type arguments (basic/derived data types) i.e., in addition to the type argument T, it can also use other arguments such as strings, function names, constant expressions, and built-in data types.
For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.
C++ Class Template with multiple parameters You can also use multiple parameters in your class template.
std::vector
has two parameters, type and allocator. Try this
template <typename T, typename Alloc, template <typename, typename> class V> void print_container(V<T, Alloc> &con) { } print_container(vec);
This will work for vector
, list
, etc., but will not work with map
, set
.
However, since you use auto
you can use C++11 and then you can to this:
template <typename T, template <typename, typename...> class V, typename... Args> void print_container(V<T, Args...> &con)
or
template <template <typename, typename...> class V, typename... Args> void print_container(V<Args...> &con)
and of course most simple way is to do something like
template<typename C> void print_container(C& con)
probably with some checks for deduce, that C
is really container.
template<typename C> auto print_container(C& con) -> decltype(con.begin(), void())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With