当前位置:   article > 正文

c++参数包的实现_c++ 参数包对象的设计

c++ 参数包对象的设计

在开发过程中,在写一些回调函数的过程中,常常希望参数是不确定、可变的,这个时候我就希望能有一个参数包,各种参数都可以塞到参数包里面,然后将该参数包作为一个参数。

之前一直使用tuple或结构体指针来实现该功能,但这两者在使用过程中还是有些不方便,于是就想自己写一个参数包的类。

boost库中有一个any类型,可作为参数包中参数的载体,可自行从boost中摘抄过来。我这边也提供一份代码:

  1. #ifndef class_any
  2. #define class_any
  3. #include <typeinfo>
  4. class any
  5. {
  6. public:
  7. any()
  8. : m_content(nullptr)
  9. {}
  10. //构造过程中,将传入参数复制给holder模板类
  11. template<typename ValueType>
  12. any(const ValueType &value)
  13. : m_content(new holder<ValueType>(value))
  14. {}
  15. any(const any &other)
  16. : m_content(other.m_content ? other.m_content->clone() : 0)
  17. {}
  18. ~any()
  19. {
  20. delete m_content;
  21. }
  22. any &swap(any &rhs)
  23. {
  24. std::swap(m_content, rhs.m_content);
  25. return *this;
  26. }
  27. template<typename ValueType>
  28. any &operator=(const ValueType &rhs)
  29. {
  30. any(rhs).swap(*this);
  31. return *this;
  32. }
  33. any &operator=(const any &rhs)
  34. {
  35. any(rhs).swap(*this);
  36. return *this;
  37. }
  38. public:
  39. bool empty() const
  40. {
  41. return !m_content;
  42. }
  43. const std::type_info &type() const
  44. {
  45. return m_content ? m_content->type() : typeid(void);
  46. }
  47. private:
  48. //一个非模板类的基类用于创建非模板类指针
  49. class placeholder
  50. {
  51. public:
  52. virtual ~placeholder()
  53. {}
  54. public:
  55. virtual const std::type_info &type() const = 0;
  56. virtual placeholder *clone() const = 0;
  57. };
  58. //继承placeholder类,并添加一个模板用于存储各种类型的参数
  59. template<typename ValueType>
  60. class holder : public placeholder
  61. {
  62. public:
  63. typedef ValueType value_type;
  64. holder(const ValueType &value)
  65. : m_held(value)
  66. {}
  67. public:
  68. virtual const std::type_info &type() const
  69. {
  70. return typeid(ValueType);
  71. }
  72. virtual placeholder *clone() const
  73. {
  74. return new holder(m_held);
  75. }
  76. public:
  77. ValueType m_held;
  78. };
  79. private:
  80. template<typename ValueType> friend ValueType *any_cast(any*);
  81. placeholder *m_content;
  82. };
  83. class bad_any_cast : public std::bad_cast
  84. {
  85. public:
  86. virtual const char *what() const throw()
  87. {
  88. return "bad_any_cast: "
  89. "failed conversion using any_cast";
  90. }
  91. };
  92. template<typename ValueType>
  93. ValueType *any_cast(any *operand)
  94. {
  95. return operand && operand->type() == typeid(ValueType)
  96. ? &static_cast<any::holder<ValueType>*>(operand->m_content)->m_held
  97. : 0;
  98. }
  99. template<typename ValueType>
  100. const ValueType *any_cast(const any *operand)
  101. {
  102. return any_cast<ValueType>(const_cast<any*>(operand));
  103. }
  104. template<typename ValueType>
  105. ValueType any_cast(const any &operand)
  106. {
  107. const ValueType *result = any_cast<ValueType>(&operand);
  108. return result ? *result : throw bad_any_cast();
  109. }
  110. #endif
我的参数包类parameters就是基于any类型实现的:
  1. class out_of_bound_of_parameters : public std::bad_cast
  2. {
  3. public:
  4. virtual const char *what() const throw()
  5. {
  6. return "parameters of the cross";
  7. }
  8. };
  9. class parameters
  10. :public std::vector<any>
  11. {
  12. public:
  13. parameters()
  14. {
  15. }
  16. /*
  17. 完成参数包的构造
  18. 调用示例:
  19. parameters objectname({1,std::string("1"),std::wstring(L"1")})
  20. 其中 "1" 和 L"1" 默认为字符数组类型,需要转化为非数组形式
  21. parameters *objectname = new parameters({std::function<void(void)>([](){...}),(char*)("1")})
  22. 其中[](){...}为函数类型,需要用函数指针或function模板指明函数结构;"1" 默认为字符数组类型,需要转化为非数组形式
  23. */
  24. parameters(const std::initializer_list<any> &args)
  25. {
  26. insert(begin(), args.begin(), args.end());
  27. }
  28. //在析构时清理stl容器,并释放对象
  29. ~parameters()
  30. {}
  31. /*
  32. 根据序号从参数包中把参数获取出来
  33. 其中_Type的类型,必须和参数传入时的类型完全一致,否则会抛出异常bad_any_cast
  34. 序号index不得超过参数包的参数,否则会抛出异常out_of_bound_of_parameters
  35. */
  36. template<class _Type>
  37. _Type get(const int &index)
  38. {
  39. return index < size() ?
  40. any_cast<_Type>(at(index)) :
  41. throw out_of_bound_of_parameters();
  42. }
  43. //往参数包中继续添加参数,添加的参数序号自动往后分配
  44. void add(const any &data)
  45. {
  46. push_back(std::move(data));
  47. }
  48. //根据序号将参数包中的某个参数移除,后面的参数序号自动向前补位
  49. bool remove(const const int &index)
  50. {
  51. if (index < size())
  52. {
  53. erase(begin() + index);
  54. return true;
  55. }
  56. return false;
  57. }
  58. //从一个参数包中拷贝数据
  59. void copy(const parameters &args)
  60. {
  61. assign(args.begin(), args.end());
  62. }
  63. };

都是很简单的代码,但parameters这个类在实际使用过程中十分方便,除了之前提到过的回调函数,其他通信过程以parameters传递参数也十分方便。


版权声明:本文为博主原创文章,未经博主允许不得转载。

https://blog.csdn.net/sjtxwangxin


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/576942
推荐阅读
相关标签
  

闽ICP备14008679号