siplasplas
A library for C++ reflection and introspection
anyarg.hpp
1 #ifndef SIPLASPLAS_TYPEERASURE_ANYARG_HPP
2 #define SIPLASPLAS_TYPEERASURE_ANYARG_HPP
3 
4 #include "simpleany.hpp"
5 #include <siplasplas/utility/universal_reference.hpp>
6 
7 namespace cpp
8 {
9 
31 class AnyArg
32 {
33 public:
37  template<typename T, typename = std::enable_if_t<
38  !std::is_same<std::decay_t<T>, cpp::ConstReferenceSimpleAny>::value &&
39  !std::is_same<std::decay_t<T>, cpp::ReferenceSimpleAny>::value
40  >>
41  AnyArg(T&& value) :
42  _universalRef{cpp::universalReference(std::forward<T>(value))}
43  {
44  _typeProperties[0] = std::is_lvalue_reference<T>::value;
45  _typeProperties[1] = std::is_const<std::remove_reference_t<T>>::value;
46  _typeProperties[2] = false;
47  }
48 
49  AnyArg(const cpp::ReferenceSimpleAny& reference) :
50  _universalRef{cpp::SimpleAny32::create<cpp::ReferenceSimpleAny>(reference)}
51  {
52  _typeProperties[0] = true;
53  _typeProperties[1] = false;
54  _typeProperties[2] = true;
55  }
56 
57  AnyArg(const cpp::ConstReferenceSimpleAny& reference) :
58  _universalRef{cpp::SimpleAny32::create<cpp::ConstReferenceSimpleAny>(reference)}
59  {
60  _typeProperties[0] = true;
61  _typeProperties[1] = true;
62  _typeProperties[2] = true;
63  }
64 
73  template<typename T>
74  const T& get() const
75  {
76  if(isReferenceAny())
77  {
78  if(isConst())
79  {
80  return _universalRef.get<cpp::ConstReferenceSimpleAny>().get<T>();
81  }
82  else
83  {
84  return _universalRef.get<cpp::ReferenceSimpleAny>().get<T>();
85  }
86  }
87  else
88  {
89  if(isRvalue())
90  {
91  return _universalRef.get<cpp::UniversalReference<std::decay_t<T>, false, false>>().get();
92  }
93  else if(isConst())
94  {
95  return _universalRef.get<cpp::UniversalReference<std::decay_t<T>, true, true>>().get();
96  }
97  else
98  {
99  return _universalRef.get<cpp::UniversalReference<std::decay_t<T>, true, false>>().get();
100  }
101  }
102  }
103 
114  template<typename T>
115  T& get()
116  {
117  if(isReferenceAny())
118  {
119  if(isConst())
120  {
121  return const_cast<T&>(_universalRef.get<cpp::ConstReferenceSimpleAny>().get<T>());
122  }
123  else
124  {
125  return _universalRef.get<cpp::ReferenceSimpleAny>().get<T>();
126  }
127  }
128  else
129  {
130  if(isRvalue())
131  {
132  return _universalRef.get<cpp::UniversalReference<std::decay_t<T>, false, false>>().get();
133  }
134  else if(isConst())
135  {
136  throw std::runtime_error{"Cannot get a non-const reference to a const argument"};
137  }
138  else
139  {
140  return _universalRef.get<cpp::UniversalReference<std::decay_t<T>, true, false>>().get();
141  }
142  }
143  }
144 
148  bool isRvalue() const
149  {
150  return !_typeProperties[0];
151  }
152 
156  bool isLvalue() const
157  {
158  return _typeProperties[0];
159  }
160 
164  bool isConst() const
165  {
166  return _typeProperties[1];
167  }
168 
169 private:
170  cpp::SimpleAny32 _universalRef;
171  std::bitset<3> _typeProperties;
172 
173  bool isReferenceAny() const
174  {
175  return _typeProperties[2];
176  }
177 };
178 
179 }
180 
181 #endif // SIPLASPLAS_TYPEERASURE_ANYARG_HPP
auto universalReference(T &&value) -> UniversalReference< std::decay_t< T >, std::is_lvalue_reference< T >::value, std::is_const< std::remove_reference_t< T >>::value >
Creates an universal reference to the given value.
Definition: universal_reference.hpp:139
cpp::SimpleAny specialization for non-owning const references to existing objects. See cpp::ConstNonOwningStorage
Definition: simpleany.hpp:41
Definition: canary_allocator.hpp:7
AnyArg(T &&value)
Initializes an AnyArg object with a given value.
Definition: anyarg.hpp:41
bool isLvalue() const
Checks if the argument was an lvalue.
Definition: anyarg.hpp:156
Implements a copyable wrapper of an universal reference.
Definition: universal_reference.hpp:31
cpp::SimpleAny specialization for non-owning references to existing objects. See cpp::NonOwningStorag...
Definition: simpleany.hpp:162
Implements a type-erased value container with minimal value semantics requirements.
Definition: simpleany.hpp:15
const std::decay_t< T > & get() const
Returns a readonly reference to the hosted object.
Definition: simpleany.hpp:472
bool isConst() const
Checks if the argument was const.
Definition: anyarg.hpp:164
Represents a type erased function call argument.
Definition: anyarg.hpp:31
bool isRvalue() const
Checks if the argument was an rvalue.
Definition: anyarg.hpp:148