Bayeux  3.4.1
Core Foundation library for SuperNEMO
handle.h
Go to the documentation of this file.
1 /* Author(s) : Francois Mauger <mauger@lpccaen.in2p3.fr>
3  * Creation date : 2011-04-01
4  * Last modified : 2018-07-17
5  *
6  * Copyright (C) 2011-2018 Francois Mauger <mauger@lpccaen.in2p3.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or (at
11  * your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  * Description:
24  *
25  * An serializable handle object referencing an object through
26  * a hiden shared pointer.
27  *
28  */
29 #ifndef DATATOOLS_HANDLE_H
30 #define DATATOOLS_HANDLE_H
31 
32 // Standard Library:
33 #include <iostream>
34 #include <stdexcept>
35 #include <type_traits>
36 
37 // Third Party:
38 // - Boost:
39 #include <boost/shared_ptr.hpp>
40 #include <boost/smart_ptr/make_shared.hpp>
41 #include <boost/serialization/nvp.hpp>
42 #include <boost/serialization/tracking.hpp>
43 #include <boost/serialization/shared_ptr.hpp>
44 
45 // This Project:
46 #include <datatools/i_predicate.h>
47 #include <datatools/exception.h>
48 
49 namespace datatools {
50 
52  template <typename T> struct handle_predicate;
53 
113  template <typename T>
114  class handle
115  {
116  public:
117  typedef T value_type;
120 
121 
123 
144  handle(T * held_ = nullptr)
145  : _sp_(held_)
146  {
147  return;
148  }
149 
151 
162  template<typename Q,
163  typename = std::enable_if<
164  std::is_same<const Q, T>::value &&
165  std::is_const<T>::value &&
166  !std::is_const<Q>::value>>
167  handle(Q* held = nullptr)
168  : _sp_(const_cast<Q*>(held))
169  {
170  return;
171  }
172 
174  handle(const boost::shared_ptr<T> & sp_)
175  : _sp_(sp_)
176  {
177  return;
178  }
179 
181  virtual ~handle()
182  {
183  _sp_.reset();
184  return;
185  }
186 
188  bool unique() const
189  {
190  return _sp_.unique();
191  }
192 
194  // 2013-05-12 FM : Preserved until all client code use the corresponding 'operator bool'.
195  bool has_data() const
196  {
197  return _sp_.get() != nullptr;
198  }
199 
201  operator bool() const
202  {
203  return _sp_.get() != nullptr;
204  }
205 
206  void swap(handle<T> & other_)
207  {
208  _sp_.swap(other_._sp_);
209  return;
210  }
211 
214  const T & get() const
215  {
216  DT_THROW_IF(_sp_.get() == nullptr, std::logic_error, "Handle holds no data!");
217  return *_sp_;
218  }
219 
220  // 2016-12-01, FM: original version is inhibited when T is const:
221  // //! Return a non-const reference to the hosted instance.
222  // T& grab() {
223  // if (_sp_) return *_sp_;
224  // DT_THROW_IF(true, std::logic_error, "Handle holds no data!");
225  // }
226 
229  template<typename Q = T>
230  typename std::enable_if<
231  std::is_same<Q, T>::value &&
232  !std::is_const<Q>::value &&
233  !std::is_const<T>::value,
234  Q&>::type grab()
235  {
236  DT_THROW_IF(_sp_.get() == nullptr, std::logic_error, "Handle holds no data!");
237  return *_sp_;
238  }
239 
243  {
244  DT_THROW_IF(!_sp_, std::logic_error, "Handle holds no data!");
245  return _sp_.get();
246  }
247 
250  T const* operator->() const
251  {
252  DT_THROW_IF(!_sp_, std::logic_error, "Handle holds no data!");
253  return _sp_.get();
254  }
255 
256 
260  {
261  DT_THROW_IF(!_sp_, std::logic_error, "Handle holds no data!");
262  return *(_sp_.get());
263  }
264 
267  T const& operator*() const
268  {
269  DT_THROW_IF(!_sp_, std::logic_error, "Handle holds no data!");
270  return *(_sp_.get());
271  }
272 
274  void reset(T * elem_ = nullptr)
275  {
276  _sp_.reset(elem_);
277  return;
278  }
279 
281  template<typename Q = T>
282  typename std::enable_if<
283  std::is_same<Q, T>::value &&
284  !std::is_const<Q>::value &&
285  !std::is_const<T>::value,
286  handle<const Q> >::type to_const() const
287  {
288  boost::shared_ptr<const T> csp = boost::const_pointer_cast<const T, T>(_sp_);
289  return handle<const T>(csp);
290  }
291 
292  private:
293 
294  friend class boost::serialization::access;
295  template <class Archive>
296  void serialize(Archive & ar_, int /*version*/)
297  {
298  ar_ & boost::serialization::make_nvp("sp", _sp_);
299  return;
300  }
301 
302  private:
303 
304  boost::shared_ptr<T> _sp_;
305 
306  };
307 
353  template <typename T, typename... Args>
354  handle<T> make_handle(Args&& ... args)
355  {
356  // Use shared_ptr constructor for simplicity
357  return handle<T>(boost::make_shared<T>(std::forward<Args>(args)...));
358  }
359 
400  template <typename T>
401  struct handle_predicate
402  : public i_predicate<handle<T> >
403  {
404  public:
406  handle_predicate(const i_predicate<T> & predicate_,
407  bool no_data_means_false_ = true)
408  : _predicate_(predicate_)
409  , _no_data_means_false_(no_data_means_false_)
410  {
411  return;
412  }
413 
414 
416  bool operator()(const handle<T> & handle_) const
417  {
418  if (! handle_) {
419  if (_no_data_means_false_) return false;
420  DT_THROW(std::logic_error, "Handle has no data !");
421  }
422  return _predicate_(handle_.get());
423  }
424 
425  private:
426  const i_predicate<T> & _predicate_;
427  bool _no_data_means_false_;
428  };
429 
430 } // end of namespace datatools
431 
432 // From "boost/serialization/shared_ptr.hpp" :
433 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
434 namespace boost {
435  namespace serialization{
436  // don't track shared pointers
438  template<class T>
439  struct tracking_level< ::datatools::handle<T> > {
440  typedef mpl::integral_c_tag tag;
441 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
442  typedef BOOST_DEDUCED_TYPENAME mpl::int_< ::boost::serialization::track_never> type;
443 #else
444  typedef mpl::int_< ::boost::serialization::track_never> type;
445 #endif
446 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
447  BOOST_STATIC_CONSTANT(int, value = ::boost::serialization::track_never);
448 #else
449  BOOST_STATIC_CONSTANT(int, value = type::value);
450 #endif
451  };
452  }}
453 #define BOOST_SERIALIZATION_DATATOOLS_HANDLE(T)
454 #else
455 // define macro to let users of these compilers do this
456 #define BOOST_SERIALIZATION_DATATOOLS_HANDLE(T) \
457  BOOST_SERIALIZATION_SHARED_PTR(T) \
458  BOOST_CLASS_TRACKING(::datatools::handle< T >, \
459  ::boost::serialization::track_never) \
460 
461 #endif
462 
463 #endif // DATATOOLS_HANDLE_H
464 
465 // Local Variables: --
466 // mode: c++ --
467 // c-file-style: "gnu" --
468 // tab-width: 2 --
469 // End: --
handle< T > make_handle(Args &&... args)
Constructs an object of type T and wraps it in a datatools::handle.
Definition: handle.h:354
Forward declaration :
Definition: handle.h:52
void swap(handle< T > &other_)
Definition: handle.h:206
#define DT_THROW(ExceptionType, Message)
Definition: exception.h:121
mpl::int_< ::boost::serialization::track_never > type
Definition: handle.h:444
Serialization stuff for CLHEP 'vector_3d'.
Definition: portable_archive_exception.hpp:27
bool unique() const
Check if the current handle holds an uniquely referenced object.
Definition: handle.h:188
virtual ~handle()
Destructor.
Definition: handle.h:181
handle_predicate< T > predicate_type
Definition: handle.h:119
handle(const boost::shared_ptr< T > &sp_)
Constructor on a boost shared_ptr.
Definition: handle.h:174
T const * operator->() const
Definition: handle.h:250
handle_predicate(const i_predicate< T > &predicate_, bool no_data_means_false_=true)
The default constructor.
Definition: handle.h:406
T & operator *()
Definition: handle.h:259
void serialize(Archive &a_ar, geomtools::vector_3d &v_, const unsigned int a_version)
T value_type
Definition: handle.h:117
T * operator->()
Definition: handle.h:242
Utility macros for exception handling.
std::enable_if< std::is_same< Q, T >::value &&!std::is_const< Q >::value &&!std::is_const< T >::value, handle< const Q > >::type to_const() const
Return a handle instance that hosts the const instance.
Definition: handle.h:286
bool has_data() const
Return true if the internal shared pointer holds something.
Definition: handle.h:195
const T & get() const
Definition: handle.h:214
Templatized handle class that wraps a Boost shared pointer and behaves like a reference.
Definition: handle.h:114
handle(Q *held=nullptr)
A constructor from a pointer to some on-the-fly allocated instance.
Definition: handle.h:167
mpl::integral_c_tag tag
Definition: handle.h:440
A template predicate abstract class.
Definition: i_predicate.h:12
value_type & reference_type
Definition: handle.h:118
std::enable_if< std::is_same< Q, T >::value &&!std::is_const< Q >::value &&!std::is_const< T >::value, Q & >::type grab()
Definition: handle.h:234
#define DT_THROW_IF(Condition, ExceptionType, Message)
Definition: exception.h:76
void reset(T *elem_=nullptr)
Reset the internal shared pointer with a new instance.
Definition: handle.h:274
handle(T *held_=nullptr)
A constructor from a pointer to some on-the-fly allocated instance.
Definition: handle.h:144
The Bayeux/datatools library top-level namespace.
Definition: algo.h:13
bool operator()(const handle< T > &handle_) const
Call operator taking handle as input.
Definition: handle.h:416