【问题标题】:Inheriting off of a list of templated classes, when supplied with the list of template arguments当提供模板参数列表时,继承模板类列表
【发布时间】:2010-02-25 22:09:47
【问题描述】:

我正在尝试编写一些元编程代码,例如:

  • 从某个类foo<c1, c2, c3, ...> 继承会导致从key<c1>, key<c2>, key<c3>, ... 继承
  • 最简单的方法不太奏效,因为您不能多次从同一个空类继承。
  • 处理“...”部分并不漂亮(因为它是复制意大利面),但可以。

好的,下面是尝试:

template<char c0, typename THEN, typename ELSE>
struct char_if
{
    typename THEN type;
};
template<typename THEN, typename ELSE>
struct char_if<0, THEN, ELSE>
{
    typename ELSE type;
};
class emptyClass {};


template<char c> class key
{
    char getKey(){return c;}
};

template<char c0, char c1, char c2, char c3, char c4>
class inheritFromAll
{
    typename char_if<c0, key<c0>, emptyClass>::type valid;

    class inherit
        : valid
        , inheritFromAll<c1, c2, c3, c4, 0>::inherit
    {};
};

template<char c1, char c2, char c3, char c4>
class inheritFromAll<0, c1, c2, c3, c4>
{
    class inherit {};
};

template<char c0 = 0, char c1 = 0, char c2 = 0, char c3 = 0, char c4 = 0>
class whatINeedToDo
    : public inheritFromAll<c0, c1, c2, c3, c4>::inherit
{
    bool success(){return true;}

};

int main() 
{
    whatINeedToDo<'A', 'B', 'c', 'D'> experiment;
    return 0;
}

我最初虽然可以使用 Boost::Mpl 来做到这一点,但老实说我不知道​​怎么做;我不知道你如何在不明确知道... 部分的情况下传递list&lt;...&gt;

只是在做:

template<> class key<0> {};

不起作用,因为如果我有多个 0 参数,我会尝试从同一事物继承两次。 (如果您能想到解决方法,那也可以)。

我也没有尝试过宏,因为我认为我对它们的了解比对元编程的了解要少,所以它们可能是一种解决方案。

有什么想法吗?

编辑:我有一个不好的解决方案。我仍然想要一个元编程解决方案,用于学习,但不好的解决方案是:

template<char c1, char c2, char c3> class inheritFromMany
    : public key<c1>
    , public key<c2>
    , public key<c3>
{

};
template<char c1, char c2> class inheritFromMany<c1, c2, 0>
    : key<c1>
    , key<c2>
    {

    };

Edit2:哇,但我忘记了一部分。我需要将一个变量传递给 ''key'' 的构造函数——在所有情况下都是一样的,但这是必要的。

Edit3:寻址 cmets:

  • 我不希望用户多次提交同一个字符。如果他们这样做了,我只想从那个键继承一次——我的意思是,我想我没有提到那是因为你不能这样做?这就是为什么其他更简单的解决方案不起作用的原因?
  • 实际上,key 是信号/槽(通道)行为的包装器。频道保存了一个回调列表,实际上就是virtual key&lt;ch&gt;::callback。因此,从键继承可以让您访问该键的通道,让(或使)您提供回调。 keyInput&lt;ch1, ch2, ch3,...&gt; 是一个包装器,所以你不必 key&lt;ch1&gt;, key&lt;ch2&gt;, key&lt;ch3&gt;

【问题讨论】:

  • 您错过了问题中的重要信息:您想要实现什么。如果出现多次包含相同元素的列表,您希望发生什么?仅从 key&lt;ch&gt; 继承一次删除重复项?

标签: c++ templates metaprogramming multiple-inheritance


【解决方案1】:

不用你说出你真正想要实现的目标,这主要是一个学术练习......但这里是你如何使用 MPL 线性继承的一种方式:

template<class T> struct key {
    enum { value = T::value };
    char getKey() { return value; }
};

template<class Values> struct derivator 
    : mpl::inherit_linearly<
          Values
        , mpl::inherit< mpl::_1, key<mpl::_2> >
        >::type
{};

// usage:    
typedef mpl::vector_c<char, 1,2,3> values;
typedef derivator<values> generated;

// or:
derivator< mpl::vector_c<char, 1,2,3> > derived;

也许你可以在此基础上澄清你需要什么。

我需要将一个变量传递给 ''key'' 的构造函数——在所有情况下都是一样的,但这是必要的。

您的意思是要通过继承链将参数传递给所有构造函数?那就看看this question的解决方案吧。


至于在可见界面中避免mpl::vector_c,您可以使用以前的方法并通过仅在其中插入不等于零的值来在内部构建它:

template<char c, class S> struct push_char {
    typedef typename mpl::push_front<S, mpl::char_<c> >::type type;
};

template<class S> struct push_char<0, S> {
    typedef S type; // don't insert if char is 0
};

template<char c1=0, char c2=0, char c3=0>
struct char_vector { 
    // build the vector_c
    typedef 
        typename push_char<c1
      , typename push_char<c2
      , typename push_char<c3
      , mpl::vector_c<char> 
      >::type>::type>::type
    type; 
};

template<char c1=0, char c2=0, char c3=0> 
struct derivator 
    : mpl::inherit_linearly<
          typename char_vector<c1,c2,c3>::type
        , mpl::inherit< mpl::_1, key<mpl::_2> >
        >::type
{};

【讨论】:

  • 有什么办法可以避免在使用中使用mpl::vector_c
  • 当然你可以让derivator 成为一个伪可变参数模板,但是你基本上最终会复制vector_c 或类似的东西(就像大多数MPL 功能一样)。为什么你需要这样做?
  • 看起来关键位是inherit_linearly<_1>key<_2> >?
  • 是的,inherit_linearly 表达式是这里的核心。剩下的就是解决它的必要工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
  • 1970-01-01
  • 2011-06-16
  • 2011-12-19
  • 2013-01-25
  • 1970-01-01
相关资源
最近更新 更多