在给出模板参数列表的情况下,继承一个模板类列表。

4
我正在尝试编写一些元编程代码,以便实现以下内容:
  • 从某个类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<...>

只需要这样做:

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

    };

编辑2:抱歉,我忘记了一部分。我需要将一个变量传递给''key''的构造函数 - 在所有情况下都是相同的,但是这是必要的。

编辑3:回应评论:

  • 我不希望用户提交相同的字符超过一次。如果他们这样做了,我只想从那个键继承一次 - 我的意思是,我没有提到这一点是因为你不能这样做?这就是为什么其他更简单的解决方案行不通的原因吗?
  • 实际上,这个关键字是信号/插槽(通道)行为的包装器。该通道保留回调列表,实际上只是virtual key<ch>::callback。因此,从一个键继承可以让您访问该键的通道,让(或使)您提供回调函数。keyInput<ch1, ch2, ch3,...>然后是对此的包装器,因此您不必使用key<ch1>, key<ch2>, key<ch3>

2
你从问题中遗漏了一个重要的信息:你想要达到什么目标。如果给出一个包含同一元素多次的列表,你期望发生什么?只继承一次从 key<ch> 中移除重复项? - David Rodríguez - dribeas
1个回答

3
没有您明确想要实现什么,这只是一个学术性的练习...但这里有一种使用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”的构造函数 - 在所有情况下都是相同的,但这是必要的。
您的意思是您想通过继承链向所有构造函数传递参数吗?然后请查看此问题的解决方案。
关于避免在可见界面中使用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”? - Narfanator
1
当然,你可以将derivator变成一个伪可变参数模板,但这样做基本上就会复制vector_c或类似的东西(就像大多数MPL功能一样)。你到底为什么需要这样做呢? - Georg Fritzsche
看起来关键的部分是inherit_linearly<_1,key<_2>>? - Narfanator
是的,inherit_linearly 表达式在这里是核心。其余的工作都是围绕它进行的必要操作。 - Georg Fritzsche

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接