LIBINT  2.1.0-stable
any.h
1 // taken from http://codereview.stackexchange.com/questions/20058/c11-any-class
2 // and modified slightly.
3 // this code is in public domain
4 
5 #ifndef _libint2_include_libint2_any_h_
6 #define _libint2_include_libint2_any_h_
7 
8 #include <type_traits>
9 #include <utility>
10 #include <typeinfo>
11 #include <string>
12 #include <cassert>
13 
14 namespace libint2 {
15 
17  struct any
18  {
19  public:
20 
21  template<class T>
22  using StorageType = typename std::decay<T>::type;
23 
24  any() = default;
25  any(const any& that) : handle_(that.clone()) {}
26  any(any&& that) : handle_(std::move(that.handle_)) { }
27  template<typename U> any(U&& value)
28  : handle_(new handle<StorageType<U>>(std::forward<U>(value)))
29  {
30  }
31 
32  any& operator=(const any& a)
33  {
34  any tmp(a);
35  std::swap(*this, tmp);
36  return *this;
37  }
38  template <typename U>
39  any& operator=(U a)
40  {
41  any tmp(std::forward<U>(a));
42  std::swap(*this, tmp);
43  return *this;
44  }
45  any& operator=(any&& a)
46  {
47  std::swap(handle_, a.handle_);
48  return *this;
49  }
50 
51  operator bool() const { return bool(handle_); }
52 
53  template<class U> bool is() const
54  {
55  typedef StorageType<U> T;
56  auto derived = dynamic_cast<handle<T>*> (handle_.get());
57  return derived;
58  }
59 
61  template<class U>
62  StorageType<U>& as()
63  {
64  typedef StorageType<U> T;
65 
66 #if not defined(NDEBUG)
67  auto derived = dynamic_cast<handle<T>*> (handle_.get());
68  if (!derived)
69  throw std::bad_cast();
70 #else // NDEBUG
71  auto derived = static_cast<handle<T>*> (handle_.get());
72 #endif
73 
74  return derived->value;
75  }
76 
78  template<class U>
79  const StorageType<U>& as() const
80  {
81  typedef StorageType<U> T;
82 
83 #if not defined(NDEBUG)
84  auto derived = dynamic_cast<handle<T>*> (handle_.get());
85  if (!derived)
86  throw std::bad_cast();
87 #else // NDEBUG
88  auto derived = static_cast<handle<T>*> (handle_.get());
89 #endif
90 
91  return derived->value;
92  }
93 
94  template<class U>
95  operator U()
96  {
97  return as<StorageType<U>>();
98  }
99 
100 
101  private:
102  struct handle_base
103  {
104  virtual ~handle_base() {}
105 
106  virtual handle_base* clone() const = 0;
107  };
108 
109  template<typename T>
110  struct handle : handle_base
111  {
112  template<typename U> handle(U&& value) : value(std::forward<U>(value)) { }
113 
114  T value;
115 
116  handle_base* clone() const { return new handle<T>(value); }
117  };
118 
119  handle_base* clone() const
120  {
121  if (handle_)
122  return handle_->clone();
123  else
124  return nullptr;
125  }
126 
127  std::unique_ptr<handle_base> handle_;
128  };
129 
130 } // namespace libint2
131 
132 #endif // header guard
133 
Defaults definitions for various parameters assumed by Libint.
Definition: algebra.cc:23
emulates boost::any
Definition: any.h:17
const StorageType< U > & as() const
Definition: any.h:79
StorageType< U > & as()
Definition: any.h:62