Adobe Source Libraries 1.49.0
A collection of C++ libraries.
Loading...
Searching...
No Matches
serializable.hpp
Go to the documentation of this file.
1/*
2 Copyright 2013 Adobe
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5*/
6/**************************************************************************************************/
7
8#ifndef ADOBE_SERIALIZABLE_HPP
9#define ADOBE_SERIALIZABLE_HPP
10
11#include <adobe/config.hpp>
12
13#include <memory>
14#include <ostream>
15#include <type_traits>
16
18#include <adobe/typeinfo.hpp>
19
20
21/**************************************************************************************************/
22
23namespace adobe {
24
25#if __cplusplus < 202002L
26
27/**************************************************************************************************/
28
29namespace implementation {
30
31/**************************************************************************************************/
32
33template <class>
34struct sfinae_true : std::true_type {};
35
36// test_stream_insertion is a modification of http://stackoverflow.com/a/9154394
37
38template <class T, class Stream>
39static auto test_stream_insertion(int)
40 -> sfinae_true<decltype(std::declval<Stream>() << std::declval<T>())>;
41
42template <class, class>
43static auto test_stream_insertion(long) -> std::false_type;
44
45/**************************************************************************************************/
46
47} // namespace implementation
48
49/**************************************************************************************************/
50
51template <class T, class Stream>
52struct has_stream_insertion : decltype(implementation::test_stream_insertion<T, Stream>(0)) {};
53
54template <class T>
56
57/**************************************************************************************************/
58
59template <class T>
60inline typename std::enable_if<has_ostream_insertion<T>::value>::type
61ostream_insertion(std::ostream& s, const T& x) {
62 s << x;
63}
64
65template <class T>
66inline typename std::enable_if<!has_ostream_insertion<T>::value>::type
67ostream_insertion(std::ostream&, const T&) {}
68
69#else // __cplusplus < 202002L
70
71template <class T>
72inline void ostream_insertion(std::ostream& s, const T& x) {
73 if constexpr (requires { s << x; }) {
74 s << x;
75 }
76}
77#endif // __cplusplus < 202002L
78
79template <>
80inline void ostream_insertion<bool>(std::ostream& s, const bool& x) {
81 s << std::boolalpha << x << std::noboolalpha;
82}
83
84template <>
85inline void ostream_insertion<double>(std::ostream& s, const double& x) {
86 s << adobe::to_string(x);
87}
88
89/**************************************************************************************************/
90// serialize<T> is an opportunity to hook user-defined wrapper types (e.g.,
91// std::reference_wrapper)
92
93template <typename T>
94struct serialize {
95 void operator()(std::ostream& s, const T& x) const { ostream_insertion(s, x); }
96};
97
98template <typename T>
99struct serialize<std::reference_wrapper<T>> {
100 void operator()(std::ostream& s, const std::reference_wrapper<T>& x) const {
101 ostream_insertion(s, x.get());
102 }
103};
104
105/**************************************************************************************************/
106
108public:
109 template <typename T>
110 explicit serializable_t(T x) : instance_m(std::make_unique<instance<T>>(x)) {}
111
112 serializable_t(const serializable_t& x) : instance_m(x.object()._copy()) {}
113
114 serializable_t(serializable_t&& x) : instance_m(x.instance_m.release()) {}
115
116 void operator()(std::ostream& s) const { object()._out(s); }
117
118 const std::type_info& type_info() const { return object().type_info(); }
119
120 template <typename T>
121 const T& cast() const {
122 const std::type_info& type(type_info());
123
124 if (type != typeid(T))
125 throw bad_cast(type, typeid(T));
126
127 return static_cast<const instance<T>&>(object()).object_m;
128 }
129
130 template <typename T>
131 T& cast() {
132 return const_cast<T&>(const_cast<const serializable_t&>(*this).cast<T>());
133 }
134
135private:
136 struct instance_t {
137 virtual ~instance_t() {}
138
139 virtual std::unique_ptr<instance_t> _copy() const = 0;
140
141 virtual void _out(std::ostream& s) const = 0;
142 virtual const std::type_info& type_info() const = 0;
143 };
144
145 template <typename T>
146 struct instance final : instance_t {
147 explicit instance(T x) : object_m(std::move(x)) {}
148
149 std::unique_ptr<instance_t> _copy() const override {
150 return std::make_unique<instance>(object_m);
151 }
152
153 void _out(std::ostream& s) const override { ostream_insertion(s, object_m); }
154
155 const std::type_info& type_info() const override { return typeid(T); }
156
157 T object_m;
158 };
159
160 instance_t& object() { return *instance_m; }
161 const instance_t& object() const { return *instance_m; }
162
163 std::unique_ptr<instance_t> instance_m;
164};
165
166/**************************************************************************************************/
167
168inline std::ostream& operator<<(std::ostream& s, const serializable_t& x) {
169 x(s);
170
171 return s;
172}
173
174/**************************************************************************************************/
175
176} // namespace adobe
177
178/**************************************************************************************************/
179
180#endif
181
182/**************************************************************************************************/
An exception class thrown during ASL failures to cast.
Definition typeinfo.hpp:33
const std::type_info & type_info() const
serializable_t(serializable_t &&x)
void operator()(std::ostream &s) const
serializable_t(const serializable_t &x)
const T & cast() const
O to_string(double x, O out, bool precise=false)
Convert double precision floating point numbers to ascii representation.
Definition to_string.hpp:86
void ostream_insertion< bool >(std::ostream &s, const bool &x)
void ostream_insertion< double >(std::ostream &s, const double &x)
std::enable_if< has_ostream_insertion< T >::value >::type ostream_insertion(std::ostream &s, const T &x)
has_stream_insertion< T, std::ostream & > has_ostream_insertion
std::ostream & operator<<(std::ostream &s, const extents_t &x)
STL namespace.
void operator()(std::ostream &s, const std::reference_wrapper< T > &x) const
void operator()(std::ostream &s, const T &x) const