IOption.hpp
1 #ifndef OPALS_IOPTION_HPP_INCLUDED
2 #define OPALS_IOPTION_HPP_INCLUDED
3 
4 ///=============================================================================
5 /// \file IOption.hpp
6 /// \brief Abstract option classes.
7 /// \author WK
8 /// \date 20.02.2017
9 ///=============================================================================
10 
11 #include <opals/fwd.hpp>
12 #include <opals/UsageLevel.hpp>
13 #include <opals/ValueSource.hpp>
14 #include <opals/OptionNames.hpp>
15 #include <type_traits>
16 
17 namespace opals { namespace opts
18 {
19 
20  /// Enumerates all option types
21  namespace Specs
22  {
23  enum Type {
24  leaf = 1,
25  group = leaf << 1,
26  vector = group << 1,
27  array = vector << 1,
28  dim1 = vector | array
29  };
30  }
31 
32  template< Names::Type name_ >
33  struct NameT : std::integral_constant< Names::Type, name_ > {};
34 
35  struct Void;
36 
37  template<class Head_, class Tail_ = Void >
38  struct Cons
39  {
40  typedef Head_ Head;
41  typedef Tail_ Tail;
42  };
43 
44  template< class >
45  struct IsCons : std::false_type {};
46 
47  template< class Head_, class Tail_ >
48  struct IsCons< Cons< Head_, Tail_ > > : std::true_type {};
49 
50  /// Base class of all option types.
51  struct IBase
52  {
53  virtual ~IBase() {}
54  /// The option name as enumerator.
55  virtual Names::Type enumerator() const = 0;
56  /// The option name as string.
57  virtual String name() const = 0;
58  /// The option name as string, preceded by the names of its parents, if any, interspersed with '.'
59  virtual String path() const = 0;
60  /// One-liner that describes this option.
61  virtual String shortDescription() const = 0;
62  /// Longer text that describes this option in more detail.
63  virtual String longDescription() const = 0;
64  /// Returns true if this or any of its parents is read-only.
65  virtual bool readOnly() const = 0;
66  /// For a leaf, this is its own usage level. For a node, this is the minimum usage level of all of its descendants: basic < mid < pro
67  virtual UsageLevel::Type minUsageLevel() const = 0;
68  /// The sub-type of this option.
69  virtual Specs::Type specialization() const = 0;
70  };
71 
72  /// Base class of all leaves.
73  struct ILeafBase
74  : IBase
75  {
76  /// Frequency / expected skills of users that access this leaf.
77  virtual UsageLevel ::Type usageLevel() const = 0;
78  /// The context in which the value has been set.
79  virtual ValueSource::Type valueSource() const = 0;
80  /// If its value has not been set, a leaf is considered empty.
81  /** Accessing its value then raises an exception. */
82  virtual bool empty() const = 0;
83  };
84 
85  /// Leaf that holds a read-only value
86  /** \tparam name_ The leaf name.
87  \tparam readOnly_ If true, then this leaf's value may not be changed.
88  \tparam T The value type. */
89  template< Names::Type name_, bool readOnly_, class T >
90  struct ILeaf
91  : ILeafBase
92  {
93  typedef NameT<name_> Name;
94 
95  /// Get the value.
96  virtual const T &get() const = 0;
97  /// Get the value or default_ if empty.
98  virtual const T &getOr( const T &default_ ) const = 0;
99  };
100 
101  /// Leaf that holds a read-write value
102  /** \tparam name_ The leaf name.
103  \tparam T The value type. */
104  template< Names::Type name_, class T >
105  struct ILeaf< name_, false, T >
106  : ILeafBase
107  {
108  typedef NameT<name_> Name;
109  /// Get the value.
110  virtual const T &get() const = 0;
111  /// Get the value or default_ if empty.
112  virtual const T &getOr( const T &default_ ) const = 0;
113  /// Set the value.
114  virtual void set( const T &value ) = 0;
115  };
116 
117 #include <opals/IAccess.hpp>
118 
119  /// A group of member options
120  /** \tparam name_ The group name.
121  \tparam readOnly_ If true, then this group and its children may not changed.
122  \tparam Opts_ The group members.
123  Provides for each member const and non-const access functions of the respective name. */
124  template< Names::Type name_, bool readOnly_, class Opts_ >
125  struct IGroup
126  : IAcc< readOnly_, Opts_ >::Type
127  {
128  typedef NameT<name_> Name;
129  };
130 
131  /// A container of read-only options.
132  /** \tparam name_ The name of the container and its elements.
133  \tparam readOnly_ If true, then this container and its elements may not be changed.
134  \tparam Opts_ If a scalar, then the element type is ILeaf, with that scalar as value type.
135  Otherwise, it is IGroup, with the respective sequence of group members.
136  Provides access to specific elements and to the default element. */
137  template< Names::Type name_, bool readOnly_, class Opts_ >
138  struct IContainer
139  : IBase
140  {
141  typedef typename std::conditional<
145  >::type Element;
146 
147  /// The number of actual elements.
148  virtual std::size_t size() const = 0;
149 
150  /// Access the default element.
151  /** Changes to it are applied immediately to all actual elements. */
152  virtual const Element &all() const = 0;
153 
154  /// Access an actual element.
155  virtual const Element &operator[]( std::size_t idx ) const = 0;
156  };
157 
158  /// A container of read-write options.
159  /** \tparam name_ The name of the container and its elements.
160  \tparam Opts_ If a scalar, then the element type is ILeaf, with that scalar as value type.
161  Otherwise, it is IGroup, with the respective sequence of group members.
162  Provides access to specific elements and to the default element. */
163  template< Names::Type name_, class Opts_ >
164  struct IContainer< name_, false, Opts_ >
165  : IBase
166  {
167  typedef typename std::conditional<
171  >::type Element;
172 
173  /// The number of actual elements.
174  virtual std::size_t size() const = 0;
175 
176  /** \name Default element.
177  Changes to it are applied immediately to all actual elements. */
178  ///@{
179  virtual const Element &all() const = 0;
180  virtual Element &all() = 0;
181  ///}@
182 
183  /// \name Access an actual element.
184  ///@{
185  virtual const Element &operator[]( std::size_t idx ) const = 0;
186  virtual Element &operator[]( std::size_t idx ) = 0;
187  ///}@
188  };
189 
190  /// A vector of dynamic size of read-only options.
191  /** \tparam name_ The name of the vector and its elements.
192  \tparam readOnly_ If true, then this vector and its elements may not be changed.
193  \tparam Opts_ If a scalar, then the element type is ILeaf, with that scalar as value type.
194  Otherwise, it is IGroup, with the respective sequence of group members. */
195  template< Names::Type name_, bool readOnly_, class Opts_ >
196  struct IVector
197  : IContainer< name_, readOnly_, Opts_ >
198  {
199  typedef NameT<name_> Name;
200  };
201 
202  /// A vector of dynamic size of read-write options.
203  /** \tparam name_ The name of the vector and its elements.
204  \tparam Opts_ If a scalar, then the element type is ILeaf, with that scalar as value type.
205  Otherwise, it is IGroup, with the respective sequence of group members. */
206  template< Names::Type name_, class Opts_ >
207  struct IVector< name_, false, Opts_ >
208  : IContainer< name_, false, Opts_ >
209  {
210  typedef NameT<name_> Name;
211 
212  /// Set the number of elements. New elements are initialized with the default element.
213  virtual void resize( std::size_t size ) = 0;
214  };
215 
216  /// An array of fixed size N of options.
217  /** \tparam name_ The name of the array and its elements.
218  \tparam readOnly_ If true, then this array and its elements may not be changed.
219  \tparam N The number of elements.
220  \tparam Opts_ If a scalar, then the element type is ILeaf, with that scalar as value type.
221  Otherwise, it is IGroup, with the respective sequence of group members. */
222  template< Names::Type name_, bool readOnly_, std::size_t N, class Opts_ >
223  struct IArray
224  : IContainer< name_, readOnly_, Opts_ >
225  {
226  typedef NameT<name_> Name;
227  };
228 
229 } }
230 
231 #endif