【问题标题】:Inherit constructors from template base class without repeating template arguments?从模板基类继承构造函数而不重复模板参数?
【发布时间】:2013-03-25 23:05:21
【问题描述】:

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

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

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

【问题讨论】:

  • typedef base&lt;U&gt; parent;
  • @MooingDuck 您仍然必须至少重复两次(一次在派生中,一次在using 中以继承构造函数)。

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


【解决方案1】:

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

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

【讨论】:

  • 关于 unique_list_base::type GCC 之前的 typename 说:keyword ‘typename’ not allowed in this context (the base class is implicitly a type)
  • 在删除了额外的类型名并修复了我让自己感到困惑的错字之后,我能够完成这项工作。谢谢!
  • @wjl 你可以使用template&lt;typename T&gt; using unique_list_base = multi_index_container&lt;...&gt;;进一步简化它。
【解决方案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 ;
};

这样,您可以摆脱 struct 以及所有与 C++03 foobar&lt;T&gt;::type 成语一起广泛使用的相关样板。

【讨论】:

  • 不错。我最近一直在使用using,我发现它在这里再次有用! =)
  • 更好的是,这让我可以将继承的构造函数行更改为using unique_list_base&lt;T&gt;::unique_list_base;,这样更容易理解。
【解决方案3】:

简单:

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

【讨论】:

    【解决方案4】:

    实际上,与 gcc 相比,MSVC 似乎甚至不需要重复模板参数:只需编写“使用 base::base”即可。

    【讨论】:

      猜你喜欢
      • 2016-02-17
      • 2016-03-04
      • 2021-07-26
      • 2019-12-14
      • 2021-04-20
      • 2019-12-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多