arguments.h 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #pragma once
  2. #include <map>
  3. #include <string>
  4. #include <vector>
  5. namespace program {
  6. template <typename Impl> class Arguments {
  7. private:
  8. struct Argument;
  9. struct Option;
  10. template <typename, typename> struct WithDefault;
  11. public:
  12. Arguments() = default;
  13. Arguments(int argc, char const * const * const argv);
  14. protected:
  15. auto option(std::string const & name, std::string const & description = "");
  16. auto option(std::string const & name, char abbrev,
  17. std::string const & description = "");
  18. auto argument(size_t index, std::string const & name,
  19. std::string const & description = "");
  20. private:
  21. void usage() const;
  22. private:
  23. // Metadata variables
  24. bool primed_{false};
  25. std::map<std::string, std::string> argument_descriptions;
  26. std::map<size_t, std::string> argument_names;
  27. std::map<std::string, std::string> option_descriptions;
  28. std::map<std::string, std::string> option_name_mapping;
  29. // Data/Output variables
  30. std::string program;
  31. size_t optional_from{std::numeric_limits<size_t>::max()};
  32. std::vector<std::string> arguments;
  33. std::map<std::string, std::vector<std::string>> options;
  34. };
  35. template <typename Impl> struct Arguments<Impl>::Argument {
  36. Arguments<Impl> * self;
  37. size_t index;
  38. bool is_optional;
  39. std::string name;
  40. std::string description;
  41. template <typename T> auto operator=(T && value);
  42. template <typename T> operator T() const;
  43. bool primed() const;
  44. explicit operator bool() const;
  45. };
  46. template <typename Impl> struct Arguments<Impl>::Option {
  47. Arguments<Impl> * self;
  48. std::string name;
  49. char abbrev;
  50. std::string description;
  51. template <typename T> auto operator=(T && value);
  52. template <typename T> operator T() const;
  53. bool primed() const;
  54. explicit operator bool() const;
  55. };
  56. template <typename Impl>
  57. template <typename B, typename V>
  58. struct Arguments<Impl>::WithDefault {
  59. B impl;
  60. V default_value;
  61. template <typename T> operator T() const { return impl ?: T(default_value); }
  62. };
  63. }
  64. #include "arguments_impl.hpp"
  65. #define TYPED_MAIN(tname) \
  66. int typed_main(tname const & args); \
  67. int main(int argc, char const * const * const argv) try { \
  68. return typed_main(tname(argc, argv)); \
  69. } catch (program::ProgramArgumentsError const & pae) { \
  70. std::cerr << "Error in program argument handling: " << pae.what() << "\n"; \
  71. } \
  72. int typed_main(tname const & args)