PVData C++ 8.0.7
Loading...
Searching...
No Matches
anyscalar.h
1#ifndef PV_ANYSCALAR_H
2#define PV_ANYSCALAR_H
3
4#if __cplusplus>=201103L
5# include <type_traits>
6#endif
7
8#include <ostream>
9#include <exception>
10#include <map>
11
12#include <epicsAssert.h>
13
14#include <pv/templateMeta.h>
15#include <pv/typeCast.h>
16#include <pv/pvIntrospect.h> /* for ScalarType enum */
17
18namespace epics{namespace pvData{
19namespace detail {
20
21// special mangling for AnyScalar ctor to map from argument type to storage type.
22// allow construction from constants.
23template <typename T>
24struct any_storage_type { typedef T type; };
25template<> struct any_storage_type<int> { typedef int32 type; };
26template<> struct any_storage_type<unsigned> { typedef uint32 type; };
27template<> struct any_storage_type<char*> { typedef std::string type; };
28template<> struct any_storage_type<const char*> { typedef std::string type; };
29
30#if __cplusplus>=201103L
31// std::max() isn't constexpr until c++14 :(
32constexpr size_t cmax(size_t A, size_t B) {
33 return A>B ? A : B;
34}
35#endif
36
37}// namespace detail
38
51class epicsShareClass AnyScalar {
52public:
53 struct bad_cast : public std::exception {
54#if __cplusplus>=201103L
55 bad_cast() noexcept {}
56 virtual ~bad_cast() noexcept {}
57 virtual const char* what() const noexcept
58#else
59 bad_cast() throw() {}
60 virtual ~bad_cast() throw() {}
61 virtual const char* what() const throw()
62#endif
63 { return "bad_cast() type mis-match"; }
64 };
65
66private:
67 ScalarType _stype;
68
69 // always reserve enough storage for std::string or double (assumed worst case)
70#if __cplusplus>=201103L
71
72 struct wrap_t {
73 typename std::aligned_storage<detail::cmax(sizeof(std::string), sizeof(double)),
74 detail::cmax(alignof(std::string), alignof(double))
75 >::type blob[1];
76 } _wrap;
77#else
78 struct wrap_t {
79 union blob_t {
80 char data[sizeof(std::string)];
81 double align_f; // assume std::string alignment <= 8
82 } blob[1];
83 } _wrap;
84#endif
85
86 // assumed largest non-string type
87 typedef double _largest_blob;
88
89 template<typename T>
90 inline T& _as() {
91 return *reinterpret_cast<T*>(_wrap.blob);
92 }
93 template<typename T>
94 inline const T& _as() const {
95 return *reinterpret_cast<const T*>(_wrap.blob);
96 }
97public:
100 AnyScalar() : _stype((ScalarType)-1) {}
101
103 template<typename T>
104 explicit AnyScalar(T v)
105 {
106 typedef typename meta::strip_const<T>::type T2;
107 typedef typename detail::any_storage_type<T2>::type TT;
108
109 STATIC_ASSERT(sizeof(TT)<=sizeof(_wrap.blob));
110
111 new (_wrap.blob) TT(v);
112
113 // this line fails to compile when type T can't be mapped to one of
114 // the PVD scalar types.
116 }
117
121 AnyScalar(ScalarType type, const void *buf);
122
123 AnyScalar(const AnyScalar& o);
124
125#if __cplusplus>=201103L
126 AnyScalar(AnyScalar&& o) noexcept;
127#endif
128
129 inline ~AnyScalar() {clear();}
130
131 inline AnyScalar& operator=(const AnyScalar& o) {
132 AnyScalar(o).swap(*this);
133 return *this;
134 }
135
136 template<typename T>
137 inline AnyScalar& operator=(T v) {
138 AnyScalar(v).swap(*this);
139 return *this;
140 }
141
142#if __cplusplus>=201103L
143 inline AnyScalar& operator=(AnyScalar&& o) noexcept {
144 clear();
145 swap(o);
146 return *this;
147 }
148#endif
149
153 void clear();
154
155 void swap(AnyScalar& o);
156
158 inline ScalarType type() const {
159 return _stype;
160 }
161
162 inline void* unsafe() { return _wrap.blob; }
163 inline const void* unsafe() const { return _wrap.blob; }
164
165 inline bool empty() const { return _stype==(ScalarType)-1; }
166
167#if __cplusplus>=201103L
168 explicit operator bool() const { return !empty(); }
169#else
170private:
171 typedef void (AnyScalar::*bool_type)(AnyScalar&);
172public:
173 operator bool_type() const { return !empty() ? &AnyScalar::swap : 0; }
174#endif
175
179 const void* bufferUnsafe() const;
180
190 template<typename T>
191 inline
192 // T -> strip_const -> map to storage type -> add reference
194 ref() {
195 typedef typename meta::strip_const<T>::type T2;
196 typedef typename detail::any_storage_type<T2>::type TT;
197
199 throw bad_cast();
200 return reinterpret_cast<TT&>(_wrap.blob);
201 }
202
211 template<typename T>
212 inline
213 // T -> strip_const -> map to storage type -> add const reference
215 ref() const {
216 typedef typename meta::strip_const<T>::type T2;
217 typedef typename detail::any_storage_type<T2>::type TT;
218
220 throw bad_cast();
221 return reinterpret_cast<typename meta::decorate_const<TT>::type&>(_wrap.blob);
222 }
223
228 template<typename T>
229 inline
230 T as() const {
231 typedef typename meta::strip_const<T>::type T2;
232 typedef typename detail::any_storage_type<T2>::type TT;
233
234 if(_stype==(ScalarType)-1)
235 throw bad_cast();
236 TT ret;
237 castUnsafeV(1, (ScalarType)ScalarTypeID<T2>::value, &ret,
238 _stype, _wrap.blob);
239 return ret;
240 }
241
242private:
243 friend epicsShareFunc std::ostream& operator<<(std::ostream& strm, const AnyScalar& v);
244};
245
246epicsShareExtern
247std::ostream& operator<<(std::ostream& strm, const AnyScalar& v);
248
249}} // namespace epics::pvData
250
251#endif // PV_ANYSCALAR_H
constexpr complex< _Tp > & operator=(const _Tp &)
void swap(any &__x, any &__y) noexcept
basic_ostream< _CharT, _Traits > & operator<<(basic_ostream< _CharT, _Traits > &__os, const basic_string< _CharT, _Traits, _Alloc > &__str)
constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())
constexpr auto data(_Container &__cont) noexcept(noexcept(__cont.data())) -> decltype(__cont.data())
ScalarType type() const
Type code of contained value. Or (ScalarType)-1 is empty.
Definition anyscalar.h:158
meta::decorate_const< typenamedetail::any_storage_type< typenamemeta::strip_const< T >::type >::type >::type & ref() const
Definition anyscalar.h:215
AnyScalar(ScalarType type, const void *buf)
const void * bufferUnsafe() const
detail::any_storage_type< typenamemeta::strip_const< T >::type >::type & ref()
Definition anyscalar.h:194
AnyScalar(T v)
Construct from provided value.
Definition anyscalar.h:104
uint32_t uint32
Definition pvType.h:99
int32_t int32
Definition pvType.h:83
epics
Definition convert.h:21