简体   繁体   中英

How to use a template class as a template parameter?

I have a class which stores a scalar along with associated physical dimension exponents:

template <int L, int M, int T, int C, int K, int S, int I>
class Dimension<L, M, T, C, K, S, I>
{
    ...
}

I'd like to build a vector like class (Vec), with static storage, which stores an array of these objects. I would presume the Vec class template would look something like:

template <Dimension<L, M, T, C, K, S, I> D, size_t N>
class Vec
{
    ...
}

But this causes an error as the template parameter D depends on template parameters ( L , M , T , C , K , S , I ). I have tried a couple of things by brute force but I'm just guessing and would prefer to be shown the correct method by someone with expertise in the matter.

I have seen examples where template<class> is inserted into the template arguments, but I don't quite understand what it achieves or even if it's actually applicable. Thanks very much for your help.

Note that I am aware that these class examples have been implemented before, probably in better ways.

Edit: Fixed a typo and changed name of Vec class.

If I understand correctly, you need template template arguments.

Anyway, first of all remember to use the word struct (or class ) for Dimension

template <int L, int M, int T, int C, int K, int S, int I>
struct Dimension
 { };

Second, you can declare a type vect (please, not vector , that can clash with the standard std::vector ) as follows

template <typename, std::size_t>
struct vect;

as receiving a type and an unsigned integer.

Then you can implement a partial specialization (with std::cout exaple for the template integer values) as follows

template <template <int, int, int, int, int, int, int> class Dim,
         int L, int M, int T, int C, int K, int S, int I, std::size_t N>
struct vect<Dim<L, M, T, C, K, S, I>, N>
 {
   vect ()
    { std::cout << " - L: " << L << " - M: " << M << " - T: " << T
                << " - C: " << C << " - K: " << K << " - S: " << S
                << " - I: " << I << " - N: " << N << std::endl; }
 };

You can use this vect as follows

vect<Dimension<2, 3, 5, 7, 11, 13, 17>, 42> v;

This works with C++98 also.

If you can use C++11 or newer, you can use variadic arguments so the vect specialization can be simplified (a little) as follows

template <template <int...> class Dim,
         int L, int M, int T, int C, int K, int S, int I, std::size_t N>
struct vect<Dim<L, M, T, C, K, S, I>, N>
 { /* ... */ };

or, using variadic arguments, a little more

template <template <int...> class Dim, int ... Is, std::size_t N>
struct vect<Dim<Is...>, N>
 { /* ... */ };

but, in this case, it's a little more complicated to use the single Is... values.

But, if you can use at least C++11, I strongly suggest (following the example of Miles Budnek) the use of std::array .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM