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

问题描述:

如何继承模板基类的构造函数,而无需重复模板参数(和不使用宏):从模板基类继承构造函数而不重复模板参数?

例如,这并不(使用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 

有没有更好的方式来处理呢?我缺少一些语法技巧? =)

+0

'typedef base parent;' – 2013-04-12 23:16:28

+0

@MooingDuck你还得重复它至少两次(一次在派生和一次在'使用'继承构造函数)。 – Zereges 2017-08-26 19:22:51

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

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

关于uniquenamelist_base :: type GCC之前的类型名称:在此上下文中不允许使用'keyword'typename'(基类隐式为类型)' – wjl 2013-04-04 04:06:02

+0

删除了额外的typename并修复了我错误的地方,我能够完成这项工作。谢谢! – wjl 2013-04-04 04:09:00

+4

@wjl您可以使用'template using unique_list_base = multi_index_container <...>;'来进一步简化它。 – 2013-04-04 06:19:23

只是为了突出丹尼尔·弗雷解决方案,因为他并没有费心去作一个完整的答案:使用声明模板(又名模板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 ; 
}; 

这样,您就可以摆脱struct和所有被广泛用C++ 03 foobar<T>::type成语使用相关的样板。

+0

不错。我最近一直在使用'使用',我发现它在这里又很有用! =) – wjl 2013-04-04 21:24:20

+0

更好的是,这可以让我将继承的构造函数行更改为'使用unique_list_base :: unique_list_base;'这更容易理解。 – wjl 2013-04-04 21:26:24

简单:

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

事实上,看来MSVC,而不是GCC,甚至不需要重复模板参数:一个可以只写“使用基本::基地”。