Inherit constructors from the template base class without repeating template arguments?

How can I inherit constructors from the template base class without repeating the template arguments (and without using macros):

For example, this does not work (using GCC 4.8):

template <typename T> struct base {}; template <typename U> struct derived : base<U> { using base::base; }; 

It works if I repeat the arguments to the base class template:

 template <typename T> struct base {}; template <typename U> struct derived : base<U> { using base<U>::base; }; 

The problem is that ā€œUā€ can be something very complex, and this is annoying, and the error is subject to repetition. For example, here is one of my original motivating examples:

 #include <boost/multi_index_container.hpp> #include <boost/multi_index/key_extractors.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/sequenced_index.hpp> using namespace boost::multi_index; struct as_list_tag {}; struct as_set_tag {}; template <typename T> struct unique_list : multi_index_container < T, indexed_by < sequenced<tag<as_list_tag>>, ordered_unique<tag<as_set_tag>, identity<T>> > > { using multi_index_container < T, indexed_by < sequenced<tag<as_list_tag>>, ordered_unique<tag<as_set_tag>, identity<T>> > > ::multi_index_container; using as_list = as_list_tag; using as_set = as_set_tag ; }; 

I ended up working on this using a macro:

 #define MAKE_UNIQUE_LIST(template_params...)\ template <typename T>\ struct unique_list : multi_index_container template_params\ {\ using multi_index_container template_params ::multi_index_container;\ using as_list = as_list_tag;\ using as_set = as_set_tag ;\ }; MAKE_UNIQUE_LIST(< T, indexed_by < sequenced<tag<as_list_tag>>, ordered_unique<tag<as_set_tag>, identity<T>> > >) #undef MAKE_UNIQUE_LIST 

Is there a better way to approach this? What syntax trick am I missing? =)

+6
source share
4 answers

This is not ideal, but you may have a class that generates your type:

 template <typename T> struct unique_list_base { typedef multi_index_container < T, indexed_by < sequenced<tag<as_list_tag>>, ordered_unique<tag<as_set_tag>, identity<T>> > > type; }; template <typename T> struct unique_list : unique_list_base<T>::type { using unique_list_base<T>::type::multi_index_container; using as_list = as_list_tag; using as_set = as_set_tag ; }; 
+3
source

Just highlight Daniel Frey's decision, as he did not bother to make a complete answer: a template using an ad (aka template typedef) is the way to go.

 template <typename T> using unique_list_base = multi_index_container < T, indexed_by < sequenced<tag<as_list_tag>>, ordered_unique<tag<as_set_tag>, identity<T>> > >; template <typename T> struct unique_list : unique_list_base<T> { using unique_list_base<T>::multi_index_container; using as_list = as_list_tag; using as_set = as_set_tag ; }; 

This way you can get rid of the struct and all related patterns that have been widely used with the C ++ 03 foobar<T>::type idiom.

+2
source

Easy:

 template <typename U, typename thebase=base<U>> struct derived : thebase { using thebase::thebase; }; 

The disadvantage is that it changes the external interface of the template to two template arguments. You can solve the following:

 template <typename U, typename thebase=base<U>> struct derived_impl : thebase { using thebase::thebase; }; template<typename U> using derived = derived_impl<U>; 
+2
source

In fact, it seems that MSVC, unlike gcc, does not even require repeating the template argument: you can simply write "using base :: base".

0
source

All Articles