Inherit constructors from template base class without repeating template arguments?

怎甘沉沦 提交于 2020-01-21 06:54:51

问题


How do I inherit constructors from a 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 does work if I repeat the template arguments of the base class:

template <typename T>
struct base {};

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

The problem is that "U" might be something very complex and that is annoying and error prone to repeat. 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 around this by 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? Some syntax trick I am missing? =)


回答1:


It isn't perfect, but you could 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 ;
};



回答2:


Just to highlight Daniel Frey solution since he did not bothered to make a full answer: template using declaration (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 the associated boilerplate that were widely used with the C++03 foobar<T>::type idiom.




回答3:


Easy:

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

The downside is that it changes the external interface of the template to have two template arguments. You can solve that like this:

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



回答4:


Actually, it appears that MSVC, as opposed to gcc, does not even require repeating the template argument: one could just write "using base::base".



来源:https://stackoverflow.com/questions/15801630/inherit-constructors-from-template-base-class-without-repeating-template-argumen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!