@@ -54,6 +54,36 @@ safeString(dom::Value const& str);
54
54
55
55
namespace dom {
56
56
57
+ /* * Mapping traits to convert types into dom::Object.
58
+
59
+ This class should be specialized by any type that needs to be converted
60
+ to/from a @ref dom::Object. For example:
61
+
62
+ @code
63
+ template<>
64
+ struct MappingTraits<MyStruct> {
65
+ template <class IO>
66
+ static void map(IO &io, MyStruct const& s)
67
+ {
68
+ io.map("name", s.name);
69
+ io.map("size", s.size);
70
+ io.map("age", s.age);
71
+ }
72
+ };
73
+ @endcode
74
+ */
75
+ template <class T >
76
+ struct ToValue {
77
+ // Value operator()(T const& o) const;
78
+ };
79
+
80
+ // / Concept to determine if @ref ToValue is defined for a type T
81
+ template <class T >
82
+ concept HasToValue = requires(T const & o)
83
+ {
84
+ { Value (std::declval<ToValue<T>>()(o)) } -> std::same_as<Value>;
85
+ };
86
+
57
87
/* * A variant container for any kind of Dom value.
58
88
*/
59
89
class MRDOCS_DECL
@@ -90,30 +120,38 @@ class MRDOCS_DECL
90
120
91
121
template <class F >
92
122
requires
93
- function_traits_convertible_to_value<F>
123
+ function_traits_convertible_to_value<F> &&
124
+ (!HasToValue<F>)
94
125
Value (F const & f)
95
126
: Value(Function(f))
96
127
{}
97
128
98
- template <class Boolean >
99
- requires std::is_same_v <Boolean , bool >
129
+ template <std::same_as< bool > Boolean >
130
+ requires (!HasToValue <Boolean >)
100
131
Value (Boolean const & b) noexcept
101
132
: kind_(Kind::Boolean )
102
133
, b_(b)
103
134
{
104
135
}
105
136
106
137
template <std::integral T>
107
- requires (!std::same_as<T, bool > && !std::same_as<T, char >)
138
+ requires
139
+ (!std::same_as<T, bool >) &&
140
+ (!std::same_as<T, char >) &&
141
+ (!HasToValue<T>)
108
142
Value (T v) noexcept : Value(std::int64_t (v)) {}
109
143
110
144
template <std::floating_point T>
145
+ requires (!HasToValue<T>)
111
146
Value (T v) noexcept : Value(std::int64_t (v)) {}
112
147
113
148
Value (char c) noexcept : Value(std::string_view(&c, 1 )) {}
114
149
115
150
template <class Enum >
116
- requires std::is_enum_v<Enum> && (!std::same_as<Enum, dom::Kind>)
151
+ requires
152
+ std::is_enum_v<Enum> &&
153
+ (!std::same_as<Enum, dom::Kind>) &&
154
+ (!HasToValue<Enum>)
117
155
Value (Enum v) noexcept
118
156
: Value(static_cast <std::underlying_type_t <Enum>>(v))
119
157
{}
@@ -131,6 +169,7 @@ class MRDOCS_DECL
131
169
}
132
170
133
171
template <std::convertible_to<String> StringLike>
172
+ requires (!HasToValue<StringLike>)
134
173
Value(StringLike const & s)
135
174
: Value(String(s))
136
175
{
@@ -155,6 +194,12 @@ class MRDOCS_DECL
155
194
{
156
195
}
157
196
197
+ template <HasToValue T>
198
+ Value (T const & t)
199
+ : Value(ToValue<T>{}(t))
200
+ {
201
+ }
202
+
158
203
Value& operator =(Value const & other);
159
204
Value& operator =(Value&& other) noexcept ;
160
205
@@ -425,29 +470,35 @@ class MRDOCS_DECL
425
470
Value const & lhs,
426
471
Value const & rhs) noexcept ;
427
472
473
+ /* * Compare two values for inequality.
474
+ */
475
+ friend
476
+ std::strong_ordering
477
+ operator <=>(
478
+ Value const & lhs,
479
+ Value const & rhs) noexcept ;
480
+
428
481
// / @overload
429
482
template <std::convertible_to<Value> S>
430
- friend auto operator ==(
431
- S const & lhs, Value const & rhs) noexcept
483
+ friend
484
+ auto
485
+ operator <=>(
486
+ S const & lhs,
487
+ Value const & rhs) noexcept
432
488
{
433
- return Value (lhs) == rhs;
489
+ return Value (lhs) <=> rhs;
434
490
}
435
491
436
492
// / @overload
437
493
template <std::convertible_to<Value> S>
438
- friend auto operator ==(
439
- Value const & lhs, S const & rhs) noexcept
440
- {
441
- return lhs == Value (rhs);
442
- }
443
-
444
- /* * Compare two values for inequality.
445
- */
446
494
friend
447
- std::strong_ordering
495
+ auto
448
496
operator <=>(
449
497
Value const & lhs,
450
- Value const & rhs) noexcept ;
498
+ S const & rhs) noexcept
499
+ {
500
+ return lhs <=> Value (rhs);
501
+ }
451
502
452
503
/* * Add or concatenate two values.
453
504
*/
0 commit comments