Plamen
Plamen

Reputation: 660

Alternatives to using template template parameters

I currently use a template class with multiple parameters,

template<class A, class B> class M{ };

However, in the position of class A I want to insert a template class, something like

template<class C> class A{ };

The only solution I've found for doing this is to use template template parameters:

template< template<class C> class A, class B> class M{ };

In my implementation, the only parameterization of A I use is A<B>. I don't need several instantiations of A using different parameters, for example I don't need to instantiate A<int> A<double> and A<long double> in M.

Is there an alternative to the template template parameter? The reason I ask is a follow up of this thread, in which in his answer @Evan Teran says he's only once ever had to use template template parameters...

I guess a twist on my question is: are there downsides to using template template parameters?

Upvotes: 3

Views: 313

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

You can take the instantiated A<B> as an argument, then use a traits class to extract the B passed to A<B> if you need it:

template<typename T>
struct extract_b {}; // SFINAE enabled
template<template<class>class A, typename B>
struct extract_b< A<B> > {
  typedef B type;
};

// C++11, you can replace it with typename extract_b<T>::type at point of use
// if you lack support for it:
template <typename T>
using ExtractB = typename extract_b<T>::type;

template<typename A>
struct M {
  typedef ExtractB<A> B;
  // ...
};

the traits class is poorly named, but you can see that I can get the template argument out of A<B> and expose it in M<A>.

Upvotes: 1

Assuming B can somehow be determined from A<B>, you can just take one template parameter:

template <class A> class M
{
  typedef typename A::The_B_Type B;
};

Of course, The_B_Type has to be a valid typedef within A<B>. That's one of the reasons why standard library containers provide all the typedefs. For example, if the template A was std::vector, you could do this:

template <class A> class M
{
  typedef typename A::value_type B;
};

Upvotes: 2

Related Questions