2016-09-15 10 views
1

私はどこでもメタプログラミングを使用する古いプログラムに新しいコンテンツを追加しようとしています。私はまだC++ 03にいます。理由は4つのファンクションで唯一の違いの私が専門にしたくないことを、私はテンプレート関数を作っ 特定の値を取得するために呼び出します:だからここ が問題である多くのスペシャライゼーションを避けようとするメタプログラミング

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()メッセージからフィールドを取得またはゼロを返すべきです。このフィールドは、タイプが付属物なしの場合は 、またはメッセージが付属物である場合はメッセージ自体に同時に付属物ORになります。

私は付属せず、メッセージの基底クラスのようなものを必要とするなど 心耳何かを持つメッセージの拡張:その後

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

EDIT:私の形質は現在コンパイルされています。クラステンプレートは..クラステンプレートを得た期待!、そうではありません、今では

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

のパラメータ1でタイプ/値の不一致があります。この作業を行うことが可能である:

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

EDIT何とか識別された。

編集:私はこのエラーを解決 、それはこのためであった:ノーマル(非テンプレート)クラスと同様

、クラステンプレートは、注入されたクラス名(節9)を持っています。 inject-class-nameは、template-argument-listの有無にかかわらず使用できます。 template-argument-listなしで使用された場合、それはinject-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; 
    } 
}; 

答えて

2

私の頭はすべてのことを読んだ後傷つけているが、それはあなたが専門にしたい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); 
    .... 
} 
+0

私は4つのそのような価値のゲッターがそれぞれ6つのスペシャライゼーションを必要としますが、これはもっとコンパクトにする方法を見つけることができません。 – Ambrase

+0

一般的なものを見つけ出して、専門にする。メンバー関数の中には、テンプレートそのものを使用するものもあります。それらはさらにゲッターをインスタンス化します。 –

+0

それは私が達成しようとしているものです。更新された質問を見て、ヘルパーを私の特質として働かせる方法を見つけたら、すべてがコンパクトになるでしょう。 – Ambrase

関連する問題