25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

90 lines
2.7 KiB

  1. #pragma once
  2. #include <cppargs/group/member_group.h>
  3. namespace cppargs
  4. {
  5. template<typename T_instance, typename T_arg>
  6. struct member_verify_and_forward
  7. {
  8. template<typename T, typename T_enable = void>
  9. struct check
  10. {
  11. template<typename X>
  12. constexpr X&& operator()(X&& x) const
  13. { static_assert(sizeof(X) == -1, "invalid group or option type"); }
  14. };
  15. template<typename T>
  16. struct check<
  17. std::unique_ptr<T>,
  18. utl::mp::enable_if<utl::mp::is_base_of<member_owned_group<T_instance>, T>>>
  19. {
  20. template<typename X>
  21. constexpr X&& operator()(X&& x) const
  22. { return std::forward<X>(x); }
  23. };
  24. template<typename T>
  25. struct check<
  26. std::unique_ptr<T>,
  27. utl::mp::enable_if<utl::mp::is_base_of<member_option<T_instance>, T>>>
  28. {
  29. template<typename X>
  30. constexpr X&& operator()(X&& x) const
  31. { return std::forward<X>(x); }
  32. };
  33. template<typename X>
  34. constexpr decltype(auto) operator()(X&& x) const
  35. { return check<T_arg> { } (std::forward<X>(x)); }
  36. };
  37. template<
  38. typename T_owner_instance,
  39. typename T_my_instance,
  40. typename T_resolve_instance_pred>
  41. template<
  42. typename... T_args>
  43. member_group<T_owner_instance, T_my_instance, T_resolve_instance_pred>
  44. ::member_group(
  45. const group_meta& p_meta,
  46. resolve_instance_pred_type&& p_pred,
  47. T_args&&... p_args)
  48. : group (p_meta, member_verify_and_forward<T_my_instance, T_args> { } (std::forward<T_args>(p_args))...)
  49. , _predicate(p_pred)
  50. {
  51. for (auto& o : _options)
  52. {
  53. auto* x = dynamic_cast<member_option_type*>(o.get());
  54. if (!x)
  55. throw std::runtime_error("option of member group is not a suitable member option");
  56. x->_owner = this;
  57. }
  58. for (auto& g : _groups)
  59. {
  60. auto* x = dynamic_cast<sub_owned_group_type*>(g.get());
  61. if (!x)
  62. throw std::runtime_error("group of member group is not a suitable member group");
  63. x->_owner = this;
  64. }
  65. }
  66. template<
  67. typename T_owner_instance,
  68. typename T_my_instance,
  69. typename T_resolve_instance_pred>
  70. T_my_instance* member_group<T_owner_instance, T_my_instance, T_resolve_instance_pred>
  71. ::instance() const
  72. {
  73. T_owner_instance * owner_inst = nullptr;
  74. if (this->_owner)
  75. owner_inst = this->_owner->instance();
  76. auto* ret = _predicate(owner_inst);
  77. return ret;
  78. }
  79. }