元编程,试图避免许多专门化

Metaprogramming, trying to avoid many specializations

本文关键字:许多 专门化 编程      更新时间:2023-10-16

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

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

有许多不同的消息类型:

  1. MessageA: public BaseForA< MessageA >
  2. MessageB: public BaseForB< MessageB >
  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()应该从消息中获取字段或返回零。如果type没有附件,这个字段可以在message本身中。如果消息带有附件,则同时在消息本身。

我需要类似基类的消息没有附件和扩展与附件的消息比如:

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条)。注入的类名可以与模板参数列表一起使用,也可以不带模板参数列表。当不使用模板实参列表时,它相当于注入的class-name后跟<>中所包含的类模板的模板形参。当它与template-argument-list一起使用时,它引用指定的类模板特化,可以是当前的特化,也可以是另一个特化。

正确的代码:

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

看完这些后我很头疼,但是如果你只想专门化一个操作,为什么不创建一个函数函数(可能是模板化的)重载(本质上是一个静态访问者):

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