Using the template template C ++ parameters is quite difficult. I want to demonstrate the power of boost :: mpl and show a trick that allows you to describe templates, completely abandoning the template template parameters.
I will demonstrate the problem. There is a class that accepts an object type and a container type for this object.
template <typename T, typename Container> struct A { typedef Container<T> type; };
You cannot write this way; you must use the template template parameters to indicate that the
Container
itself is a template.
Correctly write like this:
template <typename T, template<typename> class Container> struct A { typedef Container<T> type; };
Use this:
typedef A<int, std::vector>::type type;
When first used, we get a compile error. We forgot that std :: vector takes two parameters, one of which is usually the default. Ok, rewrite:
template <typename T, template<typename, typename> class Container> struct A { typedef Container<T, std::allocator<T> > type; };
There are two obvious problems:
- We need to look into the implementation of std :: vector, find out what type of default is used, and then use it.
- The template we have written is not suitable if the container has more than one default template parameter.
I would like to avoid explicitly specifying the default types and the complex syntax of the template template parameters. It comes to the aid of a reception based on the use of placeholders from boost :: mpl, which are used to create lambda meta-functions.
Externally, the only difference is that it is not the container template itself that is to be transferred to our template, but the container template instantiated by the placeholder, that is, instead of
typedef A<int, std::vector>::type type;
write
typedef A<int, std::vector<boost::mpl::_1> >::type type;
To instantiate a container holder-instantiated container of the required type, use boost :: mpl :: apply:
#include <boost/mpl/apply.hpp> template <typename T, typename Container> struct A { typedef typename boost::mpl::apply<Container, T>::type type; };
Using this trick in real programming will help simplify some of your tangled patterns.