Chinaunix首页 | 论坛 | 博客
  • 博客访问: 520375
  • 博文数量: 78
  • 博客积分: 995
  • 博客等级: 准尉
  • 技术积分: 1462
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-15 20:22
个人简介

技术中沉思的时候最快乐,问题得到完美解决的时候最有成就感!

文章分类

全部博文(78)

文章存档

2013年(39)

2012年(37)

2011年(2)

分类: C/C++

2012-05-26 15:41:13

写c或者c++,代码稍微复杂点,肯定会用到union;union支持普通的不带structor的结构或者class
但绝对不支持带构造函数的class,原因其实想下也清楚;
所以一般碰到这种问题的时候,都只能走其他途径绕开这个问题;比如一般稍微复杂点的svr中用到
的状态机,状态机里面会保存request的拷贝,一般一个svr里面多类请求会公用一套fsm;需要保存所有类型
的request,如果有union的话,那就比较简单了:
class  Fsm...{
union {
TRequest1 req1;
TRequest2 req2;
TRequest3 req3;...
}request;
};
不行,所以只能采用
class  Fsm... {
TRequest1 req1;
TRequest2 req2;
TRequest3 req3;
};
这样问题有几个:
1,内存浪费,如果只有2,3类还好,如果有10来中request,那每个fsm就会无谓的占
用不必要的内存了;
2,看起来难受,用起来其实不方便,写代码写起来麻烦啰嗦,像上面那种req1,req2,req3...

想了想,于是写了个能保存带构造函数的类union来;用起来还算ok;
代码如下,另外有单元测试,用法可以参考单元测试;
现在如果需要完成fsm,就可以写成:
class  Fsm... {
ClassContainer<TRequest1, TRequest2, TRequest3> _input_req;
};

点击(此处)折叠或打开

  1. #include <stdlib.h>
  2. #include <unistd.h>
  3. #include <boost/preprocessor/repetition.hpp>
  4. #include "shortcuts_util.h"

  5. #define MAX_CLASS_NUM 21

  6. namespace _OX_
  7. {
  8. #define CREATE_STRUCT(n) \
  9.         struct T ## n {};
  10. REPEATE_MACRO(MAX_CLASS_NUM, CREATE_STRUCT);
  11. #undef CREATE_STRUCT
  12. }

  13. template<typename T0, typename T1, typename T2 = _OX_::T0, typename T3 = _OX_::T1, typename T4 = _OX_::T2, typename T5 = _OX_::T3, typename T6 = _OX_::T4,
  14.          typename T7 = _OX_::T5, typename T8 = _OX_::T6, typename T9 = _OX_::T7, typename T10 = _OX_::T8, typename T11 = _OX_::T9, typename T12 = _OX_::T10, typename T13 = _OX_::T11,
  15.          typename T14 = _OX_::T12, typename T15 = _OX_::T13, typename T16 = _OX_::T14, typename T17 = _OX_::T15, typename T18 = _OX_::T16, typename T19 = _OX_::T17, typename T20 = _OX_::T18>
  16. class ClassContainer
  17. {
  18. public:
  19.         ClassContainer() : _type(-1)
  20.         {
  21.         }
  22.         ~ClassContainer()
  23.         {
  24.                 free();
  25.         }

  26.         int get_type() const
  27.         {
  28.                 return _type;
  29.         }
  30.         
  31.         void* get_raw_data()
  32.         {
  33.                 return _cls_mem;
  34.         }

  35.         template<typename Ttarget>
  36.         Ttarget *get_class(Ttarget* target, bool strictly = false)
  37.         {
  38.                 return get_class<Ttarget>(strictly);
  39.         }

  40.         template<typename Ttarget>
  41.         Ttarget *get_class(bool strictly = false)
  42.         {
  43.                 static Ttarget target;
  44.                 int type = get_type(target);

  45.                 if (_type != type)
  46.                 {
  47.                         if (strictly)
  48.                                 assert(0);

  49.                         if (_type != -1)
  50.                                 free();
  51.                         init(type);
  52.                 }
  53.                 return (Ttarget *)_cls_mem;
  54.         }

  55. #define CREATE_TYPE_FUNC(n) \
  56.         int get_type(const T ## n & tar) const \
  57.         { \
  58.                 return n; \
  59.         }
  60.         REPEATE_MACRO(MAX_CLASS_NUM, CREATE_TYPE_FUNC);
  61. #undef CREATE_TYPE_FUNC

  62.         void init(int type)
  63.         {
  64.                 assert(_type == -1);

  65.                 switch (type)
  66.                 {
  67. #define CONSTRUCT_CLASS(n) \
  68.                 case n: { \
  69.                         ::new (_cls_mem)T ## n; \
  70.                         break; \
  71.                 }
  72.                 REPEATE_MACRO(MAX_CLASS_NUM, CONSTRUCT_CLASS);
  73. #undef CONSTRUCT_CLASS
  74.                 default:
  75.                         assert(0);
  76.                 }

  77.                 _type = type;
  78.         }

  79.         void free()
  80.         {
  81.                 if (_type == -1)
  82.                         return;
  83.                 switch (_type)
  84.                 {
  85. #define DESTORY_CLASS(n) \
  86.                 case n: { \
  87.                         ((T ## n *)_cls_mem)->~T ## n(); \
  88.                         break; \
  89.                 }
  90.                 REPEATE_MACRO(MAX_CLASS_NUM, DESTORY_CLASS);
  91. #undef DESTORY_CLASS
  92.                 default:
  93.                         assert(0);
  94.                 }
  95.                 _type = -1;
  96.         }

  97. private:
  98.         union _AllTypes {
  99. #define TYPE_SIZE(n) \
  100.                 char _f ## n[sizeof(T ## n)];
  101.                 REPEATE_MACRO(MAX_CLASS_NUM, TYPE_SIZE);
  102. #undef TYPE_SIZE
  103.         };

  104. private:
  105.         char _type;
  106.         char _cls_mem[sizeof(_AllTypes)];
  107. };


  108. /*
  109.  ******************************** UNIT TEST ********************************
  110.  */
  111. #include <gtest/gtest.h>
  112. #include <vector>
  113. #include <map>
  114. #include <string>
  115. using namespace testing;

  116. class ClassContainerTestCase : public testing::Test
  117. {
  118. };
  119. TEST_F(ClassContainerTestCase, Test)
  120. {
  121.         typedef std::vector<std::string> VType;
  122.         typedef std::map<int64_t, int> MType;

  123.         ClassContainer<VType, MType, int64_t> cls_container;
  124.         ASSERT_EQ(sizeof(cls_container), std::max(sizeof(VType), sizeof(MType)) + 1);

  125.         cls_container.get_class<VType>()->resize(100);
  126.         ASSERT_EQ((int)cls_container.get_class<VType>()->size(), 100);

  127.         MType m_buf;
  128.         m_buf[0x5555998] = 50;
  129.         m_buf[0x89898977] = 10;
  130.         m_buf[0x89898475] = 8;

  131.         *(cls_container.get_class<MType>()) = m_buf;
  132.         ASSERT_EQ((*cls_container.get_class<MType>())[0x89898977], 10);

  133.         ASSERT_TRUE(cls_container.get_class<VType>()->empty());

  134.         ASSERT_EQ(*cls_container.get_class<int64_t>(), 0);
  135. }

阅读(1624) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~