Skip to content

Commit fe6fc5e

Browse files
committed
allow forward declaration of has_ traits
1 parent 6238e35 commit fe6fc5e

5 files changed

Lines changed: 88 additions & 19 deletions

File tree

doc/pages/conversion/forward.adoc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,18 @@ Forward declarations of contextual conversions are done very similarly:
4141
----
4242
include::../../../test/doc_forward_conversion.cpp[tag=doc_forward_conversion_3,indent=0]
4343
----
44+
45+
46+
== Checking for Conversion Support
47+
48+
In some cases it might be necessary for you to check if a type is supported by
49+
JSON's conversion functions. For example, you want to provide a fallback
50+
overload for types that do not have such support. The type traits
51+
<<ref_has_value_from>> and <<ref_has_value_to>> are intended for such checks.
52+
They can also be forward-declared in case a physical dependency on JSON is
53+
not desirable.
54+
55+
[source]
56+
----
57+
include::../../../test/doc_forward_conversion.cpp[tag=doc_forward_conversion_4,indent=0]
58+
----

include/boost/json/fwd.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ template<class T>
8484
typename result_for<T, value>::type
8585
result_from_errno( int e, boost::source_location const* loc ) noexcept;
8686

87+
template<class T>
88+
struct has_value_from;
89+
90+
template<class T>
91+
struct has_value_to;
92+
8793
#endif
8894

8995
} // namespace json

include/boost/json/value_from.hpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,15 @@ value_from(
153153
If `T` can be converted to @ref value via a call to @ref value_from, the
154154
static data member `value` is defined as `true`. Otherwise, `value` is
155155
defined as `false`.
156-
157-
@see @ref value_from.
158156
*/
159-
#ifdef BOOST_JSON_DOCS
160-
template<class T>
161-
using has_value_from = __see_below__;
162-
#else
163157
template<class T>
164-
using has_value_from = detail::can_convert<
165-
detail::remove_cvref<T>, detail::value_from_conversion>;
158+
struct has_value_from
159+
#ifndef BOOST_JSON_DOCS
160+
: detail::can_convert<
161+
detail::remove_cvref<T>, detail::value_from_conversion>
162+
{}
166163
#endif
164+
;
167165

168166
} // namespace json
169167
} // namespace boost

include/boost/json/value_to.hpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -215,21 +215,18 @@ try_value_to(const value& jv)
215215

216216
/** Determine if a @ref value can be converted to `T`.
217217
218-
If @ref value can be converted to `T` via a
219-
call to @ref value_to, the static data member `value`
220-
is defined as `true`. Otherwise, `value` is
218+
If @ref value can be converted to `T` via a call to @ref value_to, the
219+
static data member `value` is defined as `true`. Otherwise, `value` is
221220
defined as `false`.
222-
223-
@see @ref value_to
224221
*/
225-
#ifdef BOOST_JSON_DOCS
226-
template<class T>
227-
using has_value_to = __see_below__;
228-
#else
229222
template<class T>
230-
using has_value_to = detail::can_convert<
231-
detail::remove_cvref<T>, detail::value_to_conversion>;
223+
struct has_value_to
224+
#ifndef BOOST_JSON_DOCS
225+
: detail::can_convert<
226+
detail::remove_cvref<T>, detail::value_to_conversion>
227+
{}
232228
#endif
229+
;
233230

234231
} // namespace json
235232
} // namespace boost

test/doc_forward_conversion.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ try_value_to( const value& jv );
3232
}
3333
// end::doc_forward_conversion_1[]
3434

35+
// tag::doc_forward_conversion_4[]
36+
namespace boost {
37+
namespace json {
38+
39+
template< class T >
40+
struct has_value_from;
41+
42+
template< class T >
43+
struct has_value_to;
44+
45+
}
46+
}
47+
// end::doc_forward_conversion_4[]
48+
3549
// tag::doc_forward_conversion_3[]
3650
namespace boost {
3751
namespace json {
@@ -156,6 +170,35 @@ tag_invoke(
156170
}
157171
// end::doc_forward_conversion_3[]
158172

173+
// tag::doc_forward_conversion_4[]
174+
175+
namespace third_party
176+
{
177+
178+
struct json_storage
179+
{
180+
boost::json::value& jv;
181+
182+
template< class T >
183+
friend
184+
typename std::enable_if< boost::json::has_value_from<T>::value >::type
185+
process(json_storage& s, T const& t)
186+
{
187+
boost::json::value_from(t, s.jv);
188+
}
189+
190+
template< class T >
191+
friend
192+
typename std::enable_if< ! boost::json::has_value_from<T>::value >::type
193+
process(json_storage& s, T const&)
194+
{
195+
boost::json::value_from("unknown value", s.jv);
196+
}
197+
};
198+
199+
}
200+
// end::doc_forward_conversion_4[]
201+
159202
#include <boost/json/value_from.hpp>
160203
#include <boost/json/value_to.hpp>
161204

@@ -193,6 +236,16 @@ class doc_forward_conversion
193236
BOOST_TEST( get<1>(addr2) == 115 );
194237
BOOST_TEST( get<2>(addr2) == 81 );
195238
BOOST_TEST( get<3>(addr2) == 22 );
239+
240+
jv.emplace_null();
241+
third_party::json_storage s{jv};
242+
process(s, addr2);
243+
BOOST_TEST(( jv == value{ 212, 115, 81, 22 } ));
244+
245+
struct some_struct {};
246+
jv.emplace_null();
247+
process(s, some_struct{});
248+
BOOST_TEST(( jv == value{ "unknown value" } ));
196249
}
197250
};
198251

0 commit comments

Comments
 (0)