Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

95 строки
3.7 KiB

  1. #pragma once
  2. #include <cpputils/misc/type_helper.h>
  3. #include <cppargs/parser/parser.h>
  4. #include <cppargs/options/member.h>
  5. #include <cppargs/misc/option_parser.h>
  6. #include <cppargs/group/member_group.inl>
  7. namespace cppargs
  8. {
  9. template<typename T_instance, typename T_predicate>
  10. constexpr decltype(auto) member_parser_base::make_option(const option_meta& meta, T_predicate&& predicate)
  11. {
  12. using instance_type = T_instance;
  13. using predicate_type = T_predicate;
  14. using member_predicate_option_type = member_predicate_option<instance_type, predicate_type>;
  15. return std::make_unique<member_predicate_option_type>(meta, std::forward<T_predicate>(predicate));
  16. }
  17. template<typename T_instance, typename T_object, typename T_value>
  18. constexpr decltype(auto) member_parser_base::make_option(const option_meta& meta, T_value T_object::*member)
  19. {
  20. static_assert(std::is_base_of<T_object, T_instance>::value, "Member pointer must be in the instance type.");
  21. using instance_type = T_instance;
  22. using value_type = T_value;
  23. auto predicate = [member](instance_type& instance, context& c)
  24. {
  25. using executor_type = option_parser<value_type>;
  26. executor_type { c, instance.*member } ( );
  27. };
  28. using predicate_type = decltype(predicate);
  29. using member_predicate_option_type = member_predicate_option<instance_type, predicate_type>;
  30. return std::make_unique<member_predicate_option_type>(
  31. option_meta::prepare(meta, member),
  32. std::move(predicate));
  33. }
  34. template<typename T_instance, typename... T_args>
  35. constexpr decltype(auto) member_parser_base::make_group(const group_meta& meta, T_args&&... args)
  36. {
  37. using owner_instance_type = T_instance;
  38. using my_instance_type = T_instance;
  39. auto predicate = [](owner_instance_type* instance)
  40. { return instance; };
  41. using predicate_type = decltype(predicate);
  42. using group_type = member_group<owner_instance_type, my_instance_type, predicate_type>;
  43. return std::make_unique<group_type>(meta, std::move(predicate), std::forward<T_args>(args)...);
  44. }
  45. template<typename T_instance, typename T_object, typename T_value, typename... T_args>
  46. constexpr decltype(auto) member_parser_base::make_group(const group_meta& meta, T_value T_object::*member, T_args&&... args)
  47. {
  48. using owner_instance_type = T_instance;
  49. using my_instance_type = T_value;
  50. auto predicate = [member](owner_instance_type* instance)
  51. {
  52. if (!instance)
  53. throw std::runtime_error("unable to resolve instance for sub group: no instance assigned");
  54. return &(instance->*member);
  55. };
  56. using predicate_type = decltype(predicate);
  57. using group_type = member_group<owner_instance_type, my_instance_type, predicate_type>;
  58. return std::make_unique<group_type>(meta, std::move(predicate), std::forward<T_args>(args)...);
  59. }
  60. template<typename T_instance>
  61. template<typename... T_args>
  62. member_parser<T_instance>::member_parser(
  63. option_ptr_type&& p_default,
  64. T_args&&... args)
  65. : base_type (std::move(p_default), _group)
  66. , _group (make_base_group(std::forward<T_args>(args)...))
  67. { update_map(); }
  68. template<typename T_instance>
  69. void member_parser<T_instance>::parse(instance_type& instance, int argc, char const * argv[]) const
  70. {
  71. auto lambda = [this]() { _instance = nullptr; };
  72. auto cleanup = std::make_unique<decltype(lambda)>(std::move(lambda));
  73. _instance = &instance;
  74. base_type::parse(argc, argv);
  75. }
  76. }