从模板基类继承构造函数而不重复模板参数?

时间:2013-04-04 02:40:16

标签: c++ templates inheritance c++11 constructor

如何从模板基类继承构造函数而不重复模板参数(并且不使用宏):

例如,这不起作用(使用GCC 4.8):

template <typename T>
struct base {};

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

如果我重复基类的模板参数,它确实有效:

template <typename T>
struct base {};

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

问题是“U”可能是非常复杂的东西,这很烦人且容易重复。例如,这是我最初的激励范例之一:

#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 ;
};

我最后通过使用宏来解决这个问题:

#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

有没有更好的方法来解决这个问题?我遗漏了一些语法技巧? =)

4 个答案:

答案 0 :(得分:3)

这不完美,但你可以有一个类来生成你的类型:

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 ;
};

答案 1 :(得分:2)

只是为了突出Daniel Frey的解决方案,因为他并不打算做出完整的答案:模板使用声明(也就是模板typedef)是要走的路。

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 ;
};

通过这种方式,您可以摆脱与{C ++ 03 struct成语广泛使用的foobar<T>::type和所有相关联的样板。

答案 2 :(得分:2)

易:

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

缺点是它将模板的外部接口更改为具有两个模板参数。你可以这样解决:

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

答案 3 :(得分:0)

实际上,与gcc相比,MSVC似乎甚至不需要重复模板参数:可以使用base :: base&#34;来编写&#34;。