iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Optional.H
Go to the documentation of this file.
1 /*! @file
2  @author Shane Grant
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 #ifndef INCLUDE_NRT_CORE_DESIGN_OPTIONAL_H
36 #define INCLUDE_NRT_CORE_DESIGN_OPTIONAL_H
37 
39 #include <functional>
40 
41 namespace nrt
42 {
43  //! A class for representing optional values
44  /*! This class is a container around some value which may or may not exist; it
45  encapsulates optional data. Optional can wrap both reference and non reference data,
46  and is by default set to be uninitialized upon creation.
47 
48  This class provides similar functionality to boost::optional but supports r-value
49  assignment and construction, unlike the boost version.
50 
51  Optional can be used as a way to have functions indicate that they will not be returning
52  a valid value. Consider:
53 
54  @code
55  Optional<double> sqrt( double n );
56 
57  auto result = sqrt( -3.14 );
58  result.ifSet( [](double d){ std::cout << "Valid result!\n"; } ).otherwise( [](){ std::cout << "Invalid result!\n"; } );
59  // If we pass in a negative number here, we do not want to return a valid double.
60  // We can instead return an empty optional that can be checked using various means and properly ignored
61  // if invalid
62  @endcode
63 
64  Consider also the case of reference arguments to a function which may be considered optional. In C, these could
65  be represented by a pointer to some type. C++ does not offer a way to have references be NULL, so there is no way
66  to easily indicate that a parameter should not be calculated or not be used:
67 
68  @code
69  void myFunction( int required, Optional<double&> optionalDouble = OptionalEmpty )
70  {
71  if( optionalDouble )
72  *optionalDouble = 3.14;
73  }
74  // note the use of OptionalEmpty to provide a default value for any Optional type indicating that
75  // it should be invalid
76  @endcode
77 
78  @warning Accessing the value of an uninitialized Optional will result in undefined behavior. Make sure that
79  it is initialized before attempting to read or write.
80 
81  Also see: @ref OptionalReference for details on reference instantiation and
82  @ref OptionalValue for value type instantiation.
83 
84  @tparam T The type to make optional. Can be a reference. */
85  template <class T>
86  class Optional : public OptionalBase<typename std::remove_reference<T>::type, std::is_reference<T>::value>
87  {
88  private:
89  //! The base type we inherit from
90  typedef OptionalBase<typename std::remove_reference<T>::type, std::is_reference<T>::value> ParentType;
91  //! The argument type for copy construction
92  typedef typename ParentType::ArgumentTypeCopy ArgumentTypeCopy;
93  //! The argument type for move construction
94  typedef typename ParentType::ArgumentTypeMove ArgumentTypeMove;
95 
96  public:
97  //! Default construction, will be marked invalid
98  Optional();
99 
100  //! Construct from an OptionalNoneType, will be marked invalid
101  Optional( OptionalNoneType const & /* none */ );
102 
103  //! Copy construction, will inherit the validity of the other Optional
104  Optional( Optional const & other );
105 
106  //! Copy construct from a reference type assuming we are not a reference
107  /*! This constructor only allows construction in the reference->value direction
108  and requires that the types are identical.
109 
110  @tparam U The type of the other Optional, which should be a T reference
111  @param other The Optional that holds a reference of the same type */
112  template <class U>
113  Optional( Optional<U> const & other,
114  typename std::enable_if<!std::is_reference<T>::value &&
115  std::is_reference<U>::value &&
116  std::is_same<typename std::remove_reference<U>::type, T>::value,
117  bool>::type = false );
118 
119  //! Invalid copy constructor
120  /*! This constructor will fail to compile since it represents creating a reference Optional from
121  a non reference Optional of the same type. Static asserts will provide a more descriptive error */
122  template <class U>
123  Optional( Optional<U> const & other,
124  typename std::enable_if<std::is_reference<T>::value &&
125  !std::is_reference<U>::value &&
126  std::is_same<typename std::remove_reference<T>::type, U>::value,
127  bool>::type = false );
128 
129  //! Move construction
130  /*! Move construction will always invalidate the moved Optional */
131  Optional( Optional && other );
132 
133  //! Move construct from a reference type assuming we are not a reference
134  /*! This constructor only allows construction in the reference->value direction
135  and requires that the types are identical.
136 
137  Move construction will always invalidate the moved Optional.
138 
139  @tparam U The type of the other Optional, which should be a T reference
140  @param other The Optional that holds a reference of the same type. other will be invalidated after moving */
141  template <class U>
142  Optional( Optional<U> && other,
143  typename std::enable_if<!std::is_reference<T>::value &&
144  std::is_reference<U>::value &&
145  std::is_same<typename std::remove_reference<U>::type, T>::value,
146  bool>::type = false );
147 
148  //! Invalid move constructor
149  /*! This constructor will fail to compile since it represents creating a reference Optional from
150  a non reference Optional of the same type. Static asserts will provide a more descriptive error */
151  template <class U>
152  Optional( Optional<U> && /*other*/,
153  typename std::enable_if<std::is_reference<T>::value &&
154  !std::is_reference<U>::value &&
155  std::is_same<typename std::remove_reference<T>::type, U>::value,
156  bool>::type = false );
157 
158  //! Construct from our value type
159  /*! @param otherT The type of otherT depends upon whether this is a reference Optional or a value Optional.
160  For references, the argument copy type will be a non const refernce. For values, the
161  argument copy type will be a const reference. */
162  Optional( ArgumentTypeCopy otherT );
163 
164  //! Construct from from an r-value to our value type
165  /*! This constructor will only be available if we are not a reference Optional. References cannot
166  be constructed from r-values.
167 
168  @tparam U The type of the parameter, which should match our type T.
169  @param otherT The value to initialize with. */
170  template <class U>
171  Optional( U && otherT,
172  typename std::enable_if<!std::is_reference<T>::value &&
173  std::is_same<U, typename std::remove_reference<T>::type>::value,
174  bool>::type = false );
175 
176  //! Invalid construction from an r-value to our value type
177  /*! This constructor will fail to compile due to static assertions describing the reason for failure.
178  This will only happen in the event that a reference Optional is initialized with a r-value to the value type */
179  template <class U>
180  Optional( U && /* otherT */,
181  typename std::enable_if<std::is_reference<T>::value &&
182  std::is_same<U, typename std::remove_reference<T>::type>::value,
183  bool>::type = false );
184 
185  Optional & operator=(Optional const & other) = default;
186 
187  //! Inherit all assignment operators
188  using ParentType::operator=;
189 
190  //! Inherit conversion to bool
191  using ParentType::operator bool;
192 
193  //! Inherit star operator
194  using ParentType::operator*;
195 
196  //! Inherit arrow operator
197  using ParentType::operator->;
198 
199  //! Inherit test for whether we have a value
200  using ParentType::isSet;
201 
202  //! Inherit clearing
203  using ParentType::clear;
204 
205  //! Inherit infer type for compile time decltype use
206  using ParentType::inferType;
207 
208  //! Apply a functor to the contents of this Optional if it is set
209  /*! This, in conjunction with otherwise(), provides a clean interface to deal with
210  Optional objects that may or may not actually contain values.
211 
212  @code
213  Optional<int> myOptional;
214  myOptional.ifSet( [](int x){ std::cout << "Had an int: " << x << std::endl; } ).otherwise( [](){ std::cout << "No value!" << std::endl; } );
215  @endcode */
216  Optional & ifSet( std::function<void(ArgumentTypeCopy)> func );
217 
218  //! Const version of ifSet
219  Optional const & ifSet( std::function<void(ArgumentTypeCopy)> func ) const;
220 
221  //! Apply a functor to the contents of this Optional if it is NOT set
222  /*! This is intended to be used in conjunction with ifSet() to form an if/else pair
223  over an Optional. */
224  void otherwise( std::function<void()> func ) const;
225  }; // class Optional
226 } // namespace nrt
227 
229 
230 #endif // INCLUDE_NRT_CORE_DESIGN_OPTIONAL_H