如何使用不同的命名空间初始化派生C ++类中的模板静态成员

时间:2014-05-21 07:44:52

标签: c++ templates macros namespaces static-members

我有以下基类:

 namespace n1 {

    template <class T, typename A>
    class FSM
    {
      protected:
        typedef void (T::*pfun)();
        typedef std::map<A, pfun > transition_table_t;
        static transition_table_t _transition_table; 
    };

    } // namespace n1

和以下一组宏来定义派生类字段中的静态成员

#define BEGIN_TRANSITION_MAP(class_type, state_type) \
template <>  std::map< state_type, class_type::*pfun >  FSM<class_type, state_type>::_transition_table= {

#define TRANSITION_ENTRY(state, action) \
{state, action},

#define END_TRANSITION_MAP \
};

现在,在另一个cpp文件中,我定义了下一个派生类:

namespace n1{
    namespace n2{
    namespace n3{

    enum state{
        state1,
        state2,
    };

    class derive : public FSM<derive, state>
    {
        friend class FSM<derive, state>;
        void event_a();
        void event_b();
    };

    BEGIN_TRANSITION_MAP(n2::n3::derive, n2::n3::state) 
    TRANSITION_ENTRY(n2::n3::state1, &n2::n3::derive::event_a)
    TRANSITION_ENTRY(n2::n3::state2, &n2::n3::derive::event_b)
    END_TRANSITION_MAP

    }//namespace n3
    }//namespace n2
}//namespace n1

此代码在g++ 4.7下使用c++11编译好。

我想编写相同但不在派生类中执行基类friend,而无需在宏中指定所有命名空间。类似的东西:

namespace n1{
    namespace n2{
    namespace n3{

    enum state{
        state1,
        state2,
    };

    class derive : public FSM<derive, state>
    {
        void event_a();
        void event_b();   
    };

    BEGIN_TRANSITION_MAP(derive, state) 
    TRANSITION_ENTRY(state1, &derive::event_a)
    TRANSITION_ENTRY(state2,&derive::event_a)
    END_TRANSITION_MAP

    } //namespace n3
    } //namespace n2
} //namespace n1

这可能,还是有更好的方法解决这个问题?

1 个答案:

答案 0 :(得分:0)

仅在派生类中定义转换表。然后使用derived :: transition_table从基类中引用它。这被称为奇怪的重复模板模式(谷歌)。

template <typename derived>
class FSM
{
public:
  typedef std::map<state_type, event_type> transition_table_t;
  // do not define transition_table here

  void function()
  {
    // use transition table of derived type
    derived::transition_table.do_something();
  }
};

class Derived : public FSM<Derived>
{
public:
  static transition_table_t transition_table;
};