JayBeams  0.1
Another project to have fun coding.
config_attribute.hpp
Go to the documentation of this file.
1 #ifndef jb_config_attribute_hpp
2 #define jb_config_attribute_hpp
3 /**
4  * @file
5  *
6  * Breakout some of the helper classes from jb/config_object.hpp
7  *
8  * The definition of jb::config_object requires a number of helper
9  * classes to define a configuration attribute (i.e. a member of a
10  * config object). The code in jb/config_object.hpp was getting too
11  * long to keep in a single file, but these classes and the code in
12  * jb/config_recurse.hpp are also deeply inter-related so they could
13  * not be simply refactored out. This is a signal of poor design, and
14  * I welcome suggestions on how to improve it. However, it works, and
15  * the user interface is really clean.
16  */
17 
18 #ifndef jb_config_object_hpp
19 #error "This file should only be included from jb/config_object.hpp"
20 #endif // !jb_config_object_hpp
21 
22 #include <jb/config_recurse.hpp>
23 #include <utility>
24 
25 namespace jb {
26 
27 /**
28  * Helper class to easily define configuration attributes.
29  *
30  * The Jaybeams configuration framework requires all configuration
31  * objects to define accessors and modifiers for each attribute that
32  * follow this pattern:
33  *
34  * @code
35  * class Config {
36  * public:
37  * Config(); // default constructor sets to compile-time defaults.
38  *
39  * int attribute() const; // return current attribute value
40  * Config& attribute(int x); // set current value, chainable
41  * };
42  *
43  * Config cfg;
44  * cfg.attribute(1).another(2);
45  *
46  * @endcode
47  *
48  * This is a helper class to create such attributes easily.
49  *
50  * @tparam C the type of the object that contains the attribute
51  * @tparam T the type of the object contained in this attribute
52  */
53 template <typename C, typename T>
55 public:
56  typedef C container_type;
57  typedef T value_type;
58 
59  /// Swap values, containers are not changed
61  std::swap(value_, rhs.value_);
62  }
63 
64  /// Accessor
65  value_type const& operator()() const {
66  return value_;
67  }
68 
69  /// Modify value
70  container_type& operator()(value_type const& x) {
71  value_ = x;
72  return *container_;
73  }
74 
75  /// Modify value with move semantics
76  container_type& operator()(value_type&& x) {
77  value_ = x;
78  return *container_;
79  }
80 
81 private:
82  //@{
83  /**
84  * @name Constructors
85  *
86  * Notice that only the container class can create these objects.
87  */
89  explicit config_attribute(container_type* container)
90  : config_object::attribute_base(container)
91  , container_(container)
92  , value_() {
93  }
95  config_object::attribute_descriptor const& d, container_type* container)
96  : config_object::attribute_base(d, container)
97  , container_(container)
98  , value_() {
99  }
100 
101  config_attribute(container_type* container, value_type const& t)
102  : config_object::attribute_base(container)
103  , container_(container)
104  , value_(t) {
105  }
106 
108  config_object::attribute_descriptor const& d, container_type* container,
109  value_type const& t)
110  : config_object::attribute_base(d, container)
111  , container_(container)
112  , value_(t) {
113  }
114 
115  config_attribute(container_type* container, value_type&& t)
116  : config_object::attribute_base(container)
117  , container_(container)
118  , value_(std::move(t)) {
119  }
120 
122  config_object::attribute_descriptor const& d, container_type* container,
123  value_type&& t)
124  : config_object::attribute_base(d, container)
125  , container_(container)
126  , value_(std::move(t)) {
127  }
128 
129  template <typename... Args>
130  config_attribute(container_type* container, Args&&... args)
131  : config_object::attribute_base(container)
132  , container_(container)
133  , value_(std::forward<Args>(args)...) {
134  }
135 
136  template <typename... Args>
138  config_object::attribute_descriptor const& d, container_type* container,
139  Args&&... args)
140  : config_object::attribute_base(d, container)
141  , container_(container)
142  , value_(std::forward<Args>(args)...) {
143  }
144 
146  container_type* container,
148  : config_object::attribute_base(container)
149  , container_(container)
150  , value_(std::move(rhs.value_)) {
151  }
152 
154  container_type* container,
156  : config_object::attribute_base(container)
157  , container_(container)
158  , value_(rhs.value_) {
159  }
160 
163  delete;
164 
167  value_ = std::move(rhs.value_);
168  return *this;
169  }
172  value_ = rhs.value_;
173  return *this;
174  }
175  //@}
176 
177  friend struct config_recurse;
178  //@{
179  /**
180  * @name Configuration object recursion functions.
181  */
182  /// Call the right version of jb::apply_overrides for the contained value.
184  YAML::Node const& by_name, class_overrides const& by_class) override {
185  jb::config_recurse::apply_overrides(value_, by_name, by_class);
186  }
187 
188  /// Call the right version of jb::add_options for the contained value.
190  boost::program_options::options_description& options,
191  std::string const& prefix,
192  config_object::attribute_descriptor const& d) const override {
193  jb::config_recurse::add_options(options, value_, prefix, d);
194  }
195 
196  /// Call the right version of jb::apply_cmdline_values.
198  boost::program_options::variables_map const& vm,
199  std::string const& name) override {
201  }
202 
203  /// Call the right version of jb::validate.
204  void validate() const override {
206  }
207 
208  /// Print out the configuration settings in YAML format
209  YAML::Node to_yaml() const override {
211  }
212  //@}
213 
214 private:
215  container_type* const container_;
216  value_type value_;
217 };
218 
219 template <typename C, typename T>
221  config_attribute<C, T>& lhs, YAML::Node const& by_name,
222  class_overrides const& by_class) {
223  lhs.apply_overrides(by_name, by_class);
224 }
225 
226 template <typename C, typename T>
228  boost::program_options::options_description& options,
229  config_attribute<C, T> const& object, std::string const& prefix,
231  object.add_options(options, prefix, d);
232 }
233 
234 template <typename C, typename T>
237  boost::program_options::variables_map const& vm, std::string const& name) {
238  rhs.apply_cmdline_values(vm, name);
239 }
240 
241 template <typename C, typename T>
243  rhs.validate();
244 }
245 
246 template <typename C, typename T>
248  return rhs.to_yaml();
249 }
250 
251 } // namespace jb
252 
253 #endif // jb_config_attribute_hpp
Breakout some of the helper classes from jb/config_object.hpp.
config_attribute(config_object::attribute_descriptor const &d, container_type *container, Args &&... args)
static void validate(T const &, Args...)
Validate an arbitrary object.
container_type *const container_
attribute_base(attribute_descriptor const &d, config_object *container)
Constructor.
void apply_cmdline_values(boost::program_options::variables_map const &vm, std::string const &name) override
Call the right version of jb::apply_cmdline_values.
YAML::Node to_yaml() const override
Print out the configuration settings in YAML format.
config_attribute(config_object::attribute_descriptor const &d, container_type *container)
Base class for all configuration objects.
STL namespace.
std::map< std::string, YAML::Node > class_overrides
Store the overrides for each class.
Definition: merge_yaml.hpp:17
config_attribute(container_type *container, config_attribute< container_type, value_type > const &rhs)
std::string const & name() const
void swap(config_attribute< container_type, value_type > &rhs)
Swap values, containers are not changed.
config_attribute(config_object::attribute_descriptor const &d, container_type *container, value_type &&t)
container_type & operator()(value_type &&x)
Modify value with move semantics.
config_attribute(container_type *container, value_type const &t)
config_attribute & operator=(config_attribute< container_type, value_type > const &rhs)
Helper class to easily define configuration attributes.
config_attribute(container_type *container, value_type &&t)
static YAML::Node to_yaml(T const &x, Args...)
Convert an arbitrary type to a YAML representation.
value_type const & operator()() const
Accessor.
config_attribute & operator=(config_attribute< container_type, value_type > &&rhs)
void apply_overrides(YAML::Node const &by_name, class_overrides const &by_class) override
Call the right version of jb::apply_overrides for the contained value.
config_attribute(config_object::attribute_descriptor const &d, container_type *container, value_type const &t)
Define the interface to manipulate and access configuration attributes embedded in a config_object...
config_attribute(container_type *container, Args &&... args)
config_attribute(container_type *container)
void add_options(boost::program_options::options_description &options, std::string const &prefix, config_object::attribute_descriptor const &d) const override
Call the right version of jb::add_options for the contained value.
Recursively apply functions to config_object, attributes, and sequences of config objects...
static void apply_cmdline_values(T &rhs, boost::program_options::variables_map const &vm, std::string const &name, Args...)
Get a value from the cmdline values and apply it to the object.
config_attribute(container_type *container, config_attribute< container_type, value_type > &&rhs)
void validate() const override
Call the right version of jb::validate.
container_type & operator()(value_type const &x)
Modify value.
static void apply_overrides(T &lhs, YAML::Node const &by_name, class_overrides const &by_class, Args...)
Override a value with the configuration contained in a YAML::Node.
static void add_options(boost::program_options::options_description &options, T const &object, std::string const &prefix, config_object::attribute_descriptor const &d, Args...)
Implement the basic construct to create command-line options ased on a config_object.
The top-level namespace for the JayBeams library.
Definition: as_hhmmss.hpp:7