【问题标题】:How to initialize template static member in derived C++ class with different namespaces如何在具有不同命名空间的派生 C++ 类中初始化模板静态成员
【发布时间】:2014-05-21 07:44:51
【问题描述】:

我有以下基类:

 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.7c++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

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

【问题讨论】:

  • 那个代码:typedef std::map transition_table_t; 编译好吗?
  • 对不起,这是我的第一篇文章,我不知道为什么所有的 都被删除了。您还可以看到模板定义也错误。
  • 我不明白你为什么需要将派生类声明为朋友。
  • 对不起,我也简化了问题:)
  • 新示例已编辑以显示朋友课程的必要性。现在清楚了吗?

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


【解决方案1】:

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

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

【讨论】:

  • 感谢您的回复。但关键是将模板放在库中,最终用户只需要定义派生类,所以我不想让最终用户定义transition_table。此外,我希望每个模板实例化只初始化一次转换表,这就是它是静态成员的原因,并且我在执行期间从不更改
  • 无论如何你都必须让它静态化,我更新了上面的代码。您可能想看看boost::msm,它在编译时将状态机实现为静态结构。我还从中导出了一个简化版本,如果您有兴趣,可以在我的网站上找到。
猜你喜欢
  • 1970-01-01
  • 2015-08-04
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 2016-03-10
  • 1970-01-01
  • 2011-03-14
相关资源
最近更新 更多