iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OptionalHelpers.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_DETAILS_OPTIONALHELPERS_H
36 #define INCLUDE_NRT_CORE_DESIGN_DETAILS_OPTIONALHELPERS_H
37 
38 #include <utility>
39 #include <type_traits>
40 
41 //! @cond PRIVATE_NEVERDEFINED
42 namespace nrt_optional_impl
43 {
44  template <typename T>
45  struct RemoveConstRef
46  {
47  typedef typename std::remove_const<typename std::remove_reference<T>::type>::type Type;
48  };
49 
50  template <typename U>
51  struct IsCopyConstructibleNonRef
52  {
53  static const bool Value = std::is_copy_constructible<typename RemoveConstRef<U>::Type>::value;
54  };
55 
56  template <typename U>
57  struct IsCopyAssignableNonRef
58  {
59  static const bool Value = std::is_copy_assignable<typename RemoveConstRef<U>::Type>::value;
60  };
61 
62  template <typename U>
63  struct IsMoveConstructibleNonRef
64  {
65  static const bool Value = std::is_move_constructible<typename RemoveConstRef<U>::Type>::value;
66  };
67 
68  template <typename U>
69  struct IsMoveAssignableNonRef
70  {
71  static const bool Value = std::is_move_assignable<typename RemoveConstRef<U>::Type>::value;
72  };
73 
74  /////////////////////////////////////////////////////////////////////////////
75  // For the None type
76  struct OptionalNoneHelper{};
77 } // end nrt_optional_impl namespace
78 //! @endcond
79 
80 namespace nrt
81 {
82  //! A type used to indicate an empty optional
83  /*! @relates Optional */
84  typedef int nrt_optional_impl::OptionalNoneHelper::*OptionalNoneType;
85 
86  //! Provides a default value that can be used for Optional types to indicate that they are not in use
87  /*! @relates Optional */
88  OptionalNoneType const OptionalEmpty = static_cast<OptionalNoneType>( 0 );
89 
90  //! The base class for all optional types
91  /*! Also see: @ref OptionalReference for details on reference instantiation and
92  @ref OptionalValue for value type instantiation.
93  @relates Optional
94  @tparam T The type to hold, stripped of any reference
95  @tparam isReference Whether we hold a reference or not */
96  template <class T, bool isReference>
97  class OptionalBase;
98 
99  //! Reference template specialization for OptionalBase
100  /*! @tparam T The type to hold, stripped of any reference
101  @anchor OptionalReference
102  @relates Optional */
103  template <class T>
104  class OptionalBase<T, /*isReference:*/true>
105  {
106  public:
107  //! The actual type we hold
108  typedef typename std::add_lvalue_reference<T>::type ActualType;
109 
110  //! The type we expect for copy construction
111  typedef typename std::add_lvalue_reference<T>::type ArgumentTypeCopy;
112 
113  //! The type we expect for move construction
114  typedef typename std::add_rvalue_reference<T>::type ArgumentTypeMove;
115 
116  //! Default construction
117  OptionalBase();
118 
119  //! Copy construction
120  OptionalBase( OptionalBase const & other );
121 
122  //! Move construction
123  /*! Move construction will invalidate the other OptionalBase */
124  OptionalBase( OptionalBase && other );
125 
126  //! Construct from some existing T
127  OptionalBase( ActualType otherT );
128 
129  //! Cannot construct a reference to a temporary
130  OptionalBase( T && otherT ) = delete;
131 
132  //! Destructor
133  ~OptionalBase();
134 
135  //! Copy assignment
136  OptionalBase & operator=( OptionalBase const & other );
137 
138  //! Move assignment
139  /*! Move assignment will invalidate the other OptionalBase */
140  OptionalBase & operator=( OptionalBase && other );
141 
142  //! Copy assignment from a reference
143  OptionalBase & operator=( ActualType otherT );
144 
145  //! Cannot have temporary references
146  OptionalBase & operator=( T && otherT ) = delete;
147 
148  //! Used with decltype to infer our type, not callable as a function
149  ActualType inferType();
150 
151  //! Used with decltype to infer our type, not callable as a function
152  ActualType const inferType() const;
153 
154  //! Resets our content so we don't have anything
155  void clear();
156 
157  //! Checks if we have content
158  bool isSet() const;
159 
160  //! Converts to bool, giving the value of isSet()
161  explicit operator bool() const;
162 
163  //! Gets our value if it exists, otherwise returns nullptr
164  T * get();
165 
166  //! Gets our value if it exists, otherwise returns nullptr
167  T const * get() const;
168 
169  //! Gets our value if it exists, otherwise returns nullptr
170  T * operator->();
171 
172  //! Gets our value if it exists, otherwise returns nullptr
173  T const * operator->() const;
174 
175  //! Gets our value if it exists, otherwise a runtime error will occur
176  T & operator*();
177 
178  //! Gets our value if it exists, otherwise a runtime error will occur
179  T const & operator*() const;
180 
181  private:
182  //! Gets the address of our data
183  T * data();
184 
185  //! Gets teh address of our data
186  T const * data() const;
187 
188  typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType;
189 
190  static constexpr StorageType DefaultValue = StorageType(); //!< Used by default constructor so our reference_wrapper is happy
191 
192  std::reference_wrapper<T> itsReference; //!< Holds our reference
193 
194  bool itsValid; //!< Whether we have valid data
195  }; // OptionalBase<T,true>
196 
197  //! Value template specialization for OptionalBase
198  /*! @tparam T The type to hold, stripped of any reference
199  @anchor OptionalValue
200  @relates Optional */
201  template <class T>
202  class OptionalBase<T, /*isReference:*/false>
203  {
204  public:
205  //! The actual type we hold
206  typedef T ActualType;
207 
208  //! The type we expect for copy construction
209  typedef typename std::add_lvalue_reference<typename std::add_const<T>::type>::type ArgumentTypeCopy;
210 
211  //! The type we expect for move construction
212  typedef typename std::add_rvalue_reference<T>::type ArgumentTypeMove;
213 
214  //! Default construction
215  OptionalBase();
216 
217  //! Copy construction
218  OptionalBase( OptionalBase const & other );
219 
220  //! Move construction
221  /*! Move construction will invalidate the other OptionalBase */
222  OptionalBase( OptionalBase && other );
223 
224  //! Copy construction from the type we hold
225  OptionalBase( ArgumentTypeCopy otherT );
226 
227  //! Move construction from the type we hold
228  OptionalBase( ArgumentTypeMove otherT );
229 
230  //! Destructor
231  ~OptionalBase();
232 
233  //! Copy assignment
234  OptionalBase & operator=( OptionalBase const & other );
235 
236  //! Move assignment
237  /*! Move assignment will invalidate the other OptionalBase */
238  OptionalBase & operator=( OptionalBase && other );
239 
240  //! Copy assignment from the type we hold
241  OptionalBase & operator=( ArgumentTypeCopy other );
242 
243  //! Move assignment from the type we hold
244  OptionalBase & operator=( ArgumentTypeMove other );
245 
246  //! Marks this as having no valid data
247  void clear();
248 
249  //! Checks whether we have data
250  bool isSet() const;
251 
252  //! Returns the result of isSet
253  explicit operator bool() const;
254 
255  //! Used to get the type we hold at compile time with decltype
256  T & inferType();
257 
258  //! Used to get the type we hold at compile time with decltype
259  T const & inferType() const;
260 
261  //! Gets a pointer to the data
262  T * get();
263 
264  //! Gets a pointer to the const data
265  T const * get() const;
266 
267  //! Gets a pointer to the data
268  T * operator->();
269 
270  //! Gets a pointer to the const data
271  T const * operator->() const;
272 
273  //! Gets a reference to the data
274  T & operator*();
275 
276  //! Gets a const reference to the data
277  T const & operator*() const;
278 
279  private:
280  //! Gets the data
281  T * data();
282 
283  //! Gets the data (const)
284  T const * data() const;
285 
286  //! Performs assignment from some value
287  template <typename U = T>
288  typename std::enable_if<nrt_optional_impl::IsCopyConstructibleNonRef<U>::Value && nrt_optional_impl::IsCopyAssignableNonRef<U>::Value>::type
289  assign( T const & by_copy );
290 
291  //! Performs assignment from some value
292  template <typename U = T>
293  typename std::enable_if<nrt_optional_impl::IsCopyConstructibleNonRef<U>::Value && !nrt_optional_impl::IsCopyAssignableNonRef<U>::Value>::type
294  assign( T const & by_copy );
295 
296  //! Performs assignment from some value
297  template <typename U = T>
298  typename std::enable_if<!nrt_optional_impl::IsCopyConstructibleNonRef<U>::Value && nrt_optional_impl::IsCopyAssignableNonRef<U>::Value>::type
299  assign( T const & by_copy );
300 
301  //! Performs assignment from some value
302  template <typename U = T>
303  typename std::enable_if<nrt_optional_impl::IsMoveConstructibleNonRef<U>::Value && nrt_optional_impl::IsMoveAssignableNonRef<U>::Value>::type
304  assign( T && by_move );
305 
306  //! Performs assignment from some value
307  template <typename U = T>
308  typename std::enable_if<nrt_optional_impl::IsMoveConstructibleNonRef<U>::Value && !nrt_optional_impl::IsMoveAssignableNonRef<U>::Value>::type
309  assign( T && by_move );
310 
311  //! Performs assignment from some value
312  template <typename U = T>
313  typename std::enable_if<!nrt_optional_impl::IsMoveConstructibleNonRef<U>::Value && nrt_optional_impl::IsMoveAssignableNonRef<U>::Value>::type
314  assign( T && by_move );
315 
316  private:
317  typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType;
318 
319  StorageType itsData; //!< The data
320 
321  bool itsValid; //!< Whether our data is valid
322  }; // OptionalBase<T, false>
323 } // namespace nrt
324 
326 
327 #endif // INCLUDE_NRT_CORE_DESIGN_DETAILS_OPTIONALHELPERS_H