【问题标题】:Metaprogramming, trying to avoid many specializations元编程,试图避免许多专业化
【发布时间】:2016-09-15 17:11:23
【问题描述】:

我正在为到处使用元编程的旧程序添加新内容。我仍在使用 c++ 03 和 boost。 所以这里有一个问题: 我制作了模板函数,我不想专门化,因为只有四个函数调用不同才能获取特定值:

template < typename Message >
void function(const Message & message)
{
    ....
    int value = getHelper...getValue();
    ....
}

有许多不同的消息类型:

  1. MessageA: public BaseForA&lt; MessageA &gt;
  2. MessageB: public BaseForB&lt; MessageB &gt;
  3. template < typename Appendage > MessageAWithAppendage < Appendage >: public BaseForA< MessageA < Appendage > >
  4. template < typename Appendage > MessageB: public BaseForB< MessageB >: public BaseForB< MessageB < Appendage > >

还有两种附件类型:
SmallAppendage
BigAppendage

每条消息的标题中都有条件变量,取决于它 getValue() 应该从消息中获取字段或返回零。如果类型没有附加,则该字段可以在消息本身中, 或在附件中,或者如果消息带有附件,则同时在消息本身中。

对于没有附件的消息,我需要类似 Base 类的东西,对于带有附件的消息,我需要 Extended 类似:

template < typename Message >
 class Helper
 {
 public:
    virtual int getValue(const Message & msg)
    {
        if(..)
        {
            return msg.value;
        }
        ...
    }
};

template< template < class > class Message, typename Appendage >
class ExtendedHelper : public Helper < Message < Appendage > >
{
public:
    virtual int getValue(const Message<Appendage> & msg)
    {
        int value = Helper::getValue(msg);
        if(value)
        {
            return value;
        }
        return msg.appendage.getValue();
    }
};

在那之后,我认为这样的事情会起作用,但事实并非如此:

template < class Type >
struct AppendageTraits
{
    enum { appendageIncluded = false };
};

template < class Appendage >
struct AppendageTraits < MessageAWithAppendage < Appendage > >
{
    enum { appendageIncluded = true };
};

template < class Appendage >
struct AppendageTraits < MessageBWithAppendage < Appendage  > >
{
    enum { appendageIncluded = true };
};

template< typename Message , bool >
struct GetHelper
{
    Helper< Message > * operator()( )
    {
       static Helper< Message > helper;
       return &helper;
    }
};

编辑:我的特征现在可以编译了。是否有可能使这个工作:

template < typename Appendage >
struct GetHelper<MessageAWithAppendage <Appendage>, true>
{
    Helper< MessageAWithAppendage <Appendage> > * operator()( )
    {
        static Helper< MessageAWithAppendage <Appendage>, Appendage > helper;
        return &helper;
    }
};

template < typename Appendage >
struct GetHelper<MessageBWithAppendage <Appendage>, true>
{
    Helper< MessageBWithAppendage <Appendage> > * operator()( )
    {
        static ExtendedHelper< MessageBWithAppendage <Appendage>, Appendage > helper;
        return &helper;
    }
};

编辑:现在它在参数 1 处的类型/值不匹配

static ExtendedHelper< MessageAWithAppendage <Appendage>, Appendage > helper;

期望一个类模板得到..类模板!但它没有以某种方式识别。

编辑: 我解决了这个错误,是因为这个:

与普通(非模板)类一样,类模板具有注入类名称(第 9 条)。注入的类名可以与模板参数列表一起使用,也可以不与模板参数列表一起使用。当它在没有模板参数列表的情况下使用时,它等效于注入的类名后跟 中包含的类模板的模板参数。当它与模板参数列表一起使用时,它指的是指定的类模板特化,可以是当前特化或另一个特化。

正确代码:

template < typename Appendage >
struct GetHelper<MessageAWithAppendage <Appendage>, true>
{
    Helper< MessageAWithAppendage <Appendage> > * operator()( )
    {
        static Helper< MessageAWithAppendage, Appendage > helper;
        return &helper;
    }
};

template < typename Appendage >
struct GetHelper<MessageBWithAppendage <Appendage>, true>
{
    Helper< MessageBWithAppendage <Appendage> > * operator()( )
    {
        static ExtendedHelper< MessageBWithAppendage, Appendage > helper;
        return &helper;
    }
};

【问题讨论】:

    标签: c++ templates metaprogramming traits typetraits


    【解决方案1】:

    读完所有内容后我的头都疼了,但如果它只是您想要专门化的一个操作,为什么不使用(可能是模板化的)重载(本质上是静态访问者)制作一个仿函数:

    struct ValueGetter
    {
      int operator()(const MessageA& ma) const {
        return ma.whatever_we_need_to_do();
      } 
      int operator()(const MessageB& mb) const {
        return mb.whatever_we_need_to_do();
      } 
    };
    
    // this is now completely generic
    template < typename Message >
    void function(const Message & message)
    {
        ....
        ValueGetter vg;
        int value = vg(message);
        ....
    }
    

    【讨论】:

    • 我需要 4 个这样的值获取器,每个具有 6 个专业化,以防我找不到如何使它更紧凑。
    • 不断寻找常见的东西来专攻。一些成员函数本身可以是模板。他们实例化了更多的 getter。
    • 这就是我想要实现的目标。看看更新的问题,如果我现在能找到如何让 Helpers 作为我的特性工作,那么一切都会很紧凑。
    • 如果不更好地理解接口,就很难发表评论。我想帮忙,但我要登机了。希望另一个人可以接管。但是这个结构……看起来很复杂。让所有类都有兼容的接口不是更容易吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-06
    • 1970-01-01
    相关资源
    最近更新 更多