YPC  0.2.0
poption_require.h
1 #pragma once
2 #include <boost/program_options.hpp>
3 #include <iostream>
4 namespace ypc {
5 
6 namespace internal {
7 class opt_base {
8 public:
9  virtual bool check(const boost::program_options::variables_map &vm,
10  bool exit_if_fail) const = 0;
11  virtual std::string to_string() const = 0;
12 };
13 class opt : public opt_base {
14 public:
15  template <typename T> explicit opt(T &&_s) : m_value(_s) {}
16 
17  virtual auto check(const boost::program_options::variables_map &vm,
18  bool exit_if_fail) const -> bool;
19  virtual std::string to_string() const { return m_value; }
20 
21 protected:
22  std::string m_value;
23 };
24 
25 template <typename O1, typename O2> class and_opt : public opt_base {
26 public:
27  and_opt(const O1 &o1, const O2 &o2) : m_o1(o1), m_o2(o2) {}
28  virtual bool check(const boost::program_options::variables_map &vm,
29  bool exit_if_fail) const {
30  bool v1 = m_o1.check(vm, exit_if_fail);
31  bool v2 = m_o2.check(vm, exit_if_fail);
32  if (exit_if_fail && (!v1 || !v2)) {
33  std::cerr << "missing '" << m_o1.to_string() << "' and '"
34  << m_o2.to_string() << "'" << std::endl;
35  exit(-1);
36  }
37  return v1 && v2;
38  }
39 
40  virtual std::string to_string() const {
41  return m_o1.to_string() + " && " + m_o2.to_string();
42  }
43 
44 protected:
45  O1 m_o1;
46  O2 m_o2;
47 };
48 template <typename O1, typename O2> class or_opt : public opt_base {
49 public:
50  or_opt(const O1 &o1, const O2 &o2) : m_o1(o1), m_o2(o2) {}
51  virtual bool check(const boost::program_options::variables_map &vm,
52  bool exit_if_fail) const {
53  bool v1 = m_o1.check(vm, false);
54  bool v2 = m_o2.check(vm, false);
55  if (exit_if_fail && !v1 && !v2) {
56  std::cerr << "missing '" << m_o1.to_string() << "' or '"
57  << m_o2.to_string() << "'." << std::endl;
58  exit(-1);
59  }
60  return v1 || v2;
61  }
62 
63  virtual std::string to_string() const {
64  return m_o1.to_string() + " || " + m_o2.to_string();
65  }
66 
67 protected:
68  O1 m_o1;
69  O2 m_o2;
70 };
71 
72 } // namespace internal
73 
74 
75 class po {
76 public:
77  inline explicit po(const boost::program_options::variables_map &vm)
78  : m_vm(vm){};
79 
80  template <typename OT>
81  auto require(const OT &o) -> typename std::enable_if<
82  std::is_base_of<internal::opt_base,
83  typename std::remove_reference<OT>::type>::value,
84  void>::type {
85  o.check(m_vm, true);
86  };
87  template <typename OT>
88  auto require(const OT &o) -> typename std::enable_if<
89  !std::is_base_of<internal::opt_base,
90  typename std::remove_reference<OT>::type>::value,
91  void>::type {
92  require(internal::opt(o));
93  }
94 
95 protected:
96  const boost::program_options::variables_map &m_vm;
97 };
98 using opt = internal::opt;
99 
100 } // namespace ypc
101 
102 template <typename O1, typename O2>
103 auto operator&&(O1 &&lhs, O2 &&rhs) -> typename std::enable_if<
104  std::is_base_of<ypc::internal::opt_base,
105  typename std::remove_reference<O1>::type>::value &&
106  std::is_base_of<ypc::internal::opt_base,
107  typename std::remove_reference<O2>::type>::value,
109  return ypc::internal::and_opt<O1, O2>(lhs, rhs);
110 }
111 
112 template <typename O1, typename O2>
113 auto operator||(const O1 &lhs, const O2 &rhs) -> typename std::enable_if<
114  std::is_base_of<ypc::internal::opt_base, O1>::value &&
115  std::is_base_of<ypc::internal::opt_base, O2>::value,
117  return ypc::internal::or_opt<O1, O2>(lhs, rhs);
118 }
ypc::internal::opt_base
Definition: poption_require.h:7
ypc::po
Definition: poption_require.h:75
ypc::internal::and_opt
Definition: poption_require.h:25
ypc::internal::opt
Definition: poption_require.h:13
ypc::internal::or_opt
Definition: poption_require.h:48