Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[config] Remove one bindFlag() overload which does not make sense/work anymore
[simgrid.git] / include / xbt / config.hpp
1 /* Copyright (c) 2016. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #ifndef _XBT_CONFIG_HPP_
8 #define _XBT_CONFIG_HPP_
9
10 #include <cstdlib>
11
12 #include <functional>
13 #include <stdexcept>
14 #include <string>
15 #include <type_traits>
16 #include <utility>
17
18 #include <xbt/base.h>
19 #include <xbt/config.h>
20
21 namespace simgrid {
22 namespace config {
23
24 template<class T> inline
25 std::string to_string(T&& value)
26 {
27   return std::to_string(std::forward<T>(value));
28 }
29 inline std::string const& to_string(std::string& value)
30 {
31   return value;
32 }
33 inline std::string const& to_string(std::string const& value)
34 {
35   return value;
36 }
37 inline std::string to_string(std::string&& value)
38 {
39   return std::move(value);
40 }
41
42 // Get config
43
44 template<class T>
45 XBT_PUBLIC(T const&) getConfig(const char* name);
46
47 extern template XBT_PUBLIC(int const&) getConfig<int>(const char* name);
48 extern template XBT_PUBLIC(double const&) getConfig<double>(const char* name);
49 extern template XBT_PUBLIC(bool const&) getConfig<bool>(const char* name);
50 extern template XBT_PUBLIC(std::string const&) getConfig<std::string>(const char* name);
51
52 // Register:
53
54 /** Register a configuration flag
55  *
56  *  @param name        name of the option
57  *  @param description Description of the option
58  *  @param value       Initial/default value
59  *  @param callback    called with the option value
60  */
61 template<class T>
62 XBT_PUBLIC(void) declareFlag(const char* name, const char* description,
63   T value, std::function<void(const T&)> callback = std::function<void(const T&)>());
64
65 extern template XBT_PUBLIC(void) declareFlag(const char* name,
66   const char* description, int value, std::function<void(int const &)> callback);
67 extern template XBT_PUBLIC(void) declareFlag(const char* name,
68   const char* description, double value, std::function<void(double const &)> callback);
69 extern template XBT_PUBLIC(void) declareFlag(const char* name,
70   const char* description, bool value, std::function<void(bool const &)> callback);
71 extern template XBT_PUBLIC(void) declareFlag(const char* name,
72   const char* description, std::string value, std::function<void(std::string const &)> callback);
73
74 /** Bind a variable to configuration flag
75  *
76  *  @param value Bound variable
77  *  @param name  Flag name
78  *  @param description Option description
79  */
80 template<class T>
81 void bindFlag(T& value, const char* name, const char* description)
82 {
83   using namespace std;
84   declareFlag<T>(name, description, value, [&value](T const& val) {
85     value = val;
86   });
87 }
88
89 /** Bind a variable to configuration flag
90  *
91  *  <pre><code>
92  *  static int x;
93  *  simgrid::config::bindFlag(a, "x", [](int x) {
94  *    if (x < x_min || x => x_max)
95  *      throw std::range_error("must be in [x_min, x_max)")
96  *  });
97  *  </pre><code>
98  */
99 // F is a checker, F : T& -> ()
100 template<class T, class F>
101 typename std::enable_if<std::is_same<
102   void,
103   decltype( std::declval<F>()(std::declval<const T&>()) )
104 >::value, void>::type
105 bindFlag(T& value, const char* name, const char* description,
106   F callback)
107 {
108   declareFlag(name, description, value, [&value,callback](const T& val) {
109     callback(val);
110     value = std::move(val);
111   });
112 }
113
114 /** Bind a variable to configuration flag
115  *
116  *  <pre><code>
117  *  static int x;
118  *  simgrid::config::bindFlag(a, "x", [](int x) { return return x > 0; });
119  *  </pre><code>
120  */
121 // F is a predicate, F : T const& -> bool
122 template<class T, class F>
123 typename std::enable_if<std::is_same<
124   bool,
125   decltype( std::declval<F>()(std::declval<const T&>()) )
126 >::value, void>::type
127 bindFlag(T& value, const char* name, const char* description,
128   F callback)
129 {
130   declareFlag(name, description, value, [&value,callback](const T& val) {
131     if (!callback(val))
132       throw std::range_error("invalid value");
133     value = std::move(val);
134   });
135 }
136
137 /** A variable bound to a CLI option
138  *
139  *  <pre><code>
140  *  static simgrid::config::flag<int> answer("answer", "Expected answer", 42);
141  *  static simgrid::config::flag<std::string> name("name", "Ford Prefect", "John Doe");
142  *  static simgrid::config::flag<double> gamma("gamma", "Gamma factor", 1.987);
143  *  </code></pre>
144  */
145 template<class T>
146 class Flag {
147   T value_;
148 public:
149
150   /** Constructor
151    *
152    *  @param name  Flag name
153    *  @param desc  Flag description
154    *  @param value Flag initial/default value
155    */
156   Flag(const char* name, const char* desc, T value) : value_(value)
157   {
158     simgrid::config::bindFlag(value_, name, desc);
159   }
160
161   template<class F>
162   Flag(const char* name, const char* desc, T value, F callback) : value_(value)
163   {
164     simgrid::config::bindFlag(value_, name, desc, std::move(callback));
165   }
166
167   // No copy:
168   Flag(Flag const&) = delete;
169   Flag& operator=(Flag const&) = delete;
170
171   // Get the underlying value:
172   T& get() { return value_; }
173   T const& get() const { return value_; }
174
175   // Implicit conversion to the underlying type:
176   operator T&() { return value_; }
177   operator T const&() const{ return value_; }
178
179   // Basic interop with T:
180   Flag& operator=(T const& that) { value_ = that; return *this; }
181   Flag& operator=(T && that)     { value_ = that; return *this; }
182   bool operator==(T const& that) const { return value_ == that; }
183   bool operator!=(T const& that) const { return value_ != that; }
184   bool operator<(T const& that) const { return value_ < that; }
185   bool operator>(T const& that) const { return value_ > that; }
186   bool operator<=(T const& that) const { return value_ <= that; }
187   bool operator>=(T const& that) const { return value_ >= that; }
188 };
189
190 }
191 }
192
193 #endif