@@ -2302,6 +2302,16 @@ JSON_HEDLEY_DIAGNOSTIC_POP
23022302 void to_json(nlohmann::json& j, const Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
23032303 void from_json(const nlohmann::json& j, Type& t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
23042304
2305+ #ifndef JSON_USE_IMPLICIT_CONVERSIONS
2306+ #define JSON_USE_IMPLICIT_CONVERSIONS 1
2307+ #endif
2308+
2309+ #if JSON_USE_IMPLICIT_CONVERSIONS
2310+ #define JSON_EXPLICIT
2311+ #else
2312+ #define JSON_EXPLICIT explicit
2313+ #endif
2314+
23052315
23062316namespace nlohmann
23072317{
@@ -3022,6 +3032,16 @@ using get_template_function = decltype(std::declval<T>().template get<U>());
30223032template<typename BasicJsonType, typename T, typename = void>
30233033struct has_from_json : std::false_type {};
30243034
3035+ // trait checking if j.get<T> is valid
3036+ // use this trait instead of std::is_constructible or std::is_convertible,
3037+ // both rely on, or make use of implicit conversions, and thus fail when T
3038+ // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3039+ template <typename BasicJsonType, typename T>
3040+ struct is_getable
3041+ {
3042+ static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3043+ };
3044+
30253045template<typename BasicJsonType, typename T>
30263046struct has_from_json < BasicJsonType, T,
30273047 enable_if_t < !is_basic_json<T>::value >>
@@ -3507,7 +3527,7 @@ void from_json(const BasicJsonType& j, EnumType& e)
35073527
35083528// forward_list doesn't have an insert method
35093529template<typename BasicJsonType, typename T, typename Allocator,
3510- enable_if_t<std::is_convertible <BasicJsonType, T>::value, int> = 0>
3530+ enable_if_t<is_getable <BasicJsonType, T>::value, int> = 0>
35113531void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
35123532{
35133533 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
@@ -3524,15 +3544,19 @@ void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
35243544
35253545// valarray doesn't have an insert method
35263546template<typename BasicJsonType, typename T,
3527- enable_if_t<std::is_convertible <BasicJsonType, T>::value, int> = 0>
3547+ enable_if_t<is_getable <BasicJsonType, T>::value, int> = 0>
35283548void from_json(const BasicJsonType& j, std::valarray<T>& l)
35293549{
35303550 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
35313551 {
35323552 JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
35333553 }
35343554 l.resize(j.size());
3535- std::copy(j.begin(), j.end(), std::begin(l));
3555+ std::transform(j.begin(), j.end(), std::begin(l),
3556+ [](const BasicJsonType & elem)
3557+ {
3558+ return elem.template get<T>();
3559+ });
35363560}
35373561
35383562template<typename BasicJsonType, typename T, std::size_t N>
@@ -19508,7 +19532,7 @@ class basic_json
1950819532#endif
1950919533 && detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
1951019534 , int >::type = 0 >
19511- operator ValueType() const
19535+ JSON_EXPLICIT operator ValueType() const
1951219536 {
1951319537 // delegate the call to get<>() const
1951419538 return get<ValueType>();
@@ -20063,8 +20087,9 @@ class basic_json
2006320087
2006420088 @since version 1.0.0
2006520089 */
20090+ // using std::is_convertible in a std::enable_if will fail when using explicit conversions
2006620091 template < class ValueType, typename std::enable_if <
20067- std::is_convertible <basic_json_t, ValueType>::value
20092+ detail::is_getable <basic_json_t, ValueType>::value
2006820093 && !std::is_same<value_t, ValueType>::value, int >::type = 0 >
2006920094 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
2007020095 {
@@ -20075,7 +20100,7 @@ class basic_json
2007520100 const auto it = find(key);
2007620101 if (it != end())
2007720102 {
20078- return *it ;
20103+ return it->template get<ValueType>() ;
2007920104 }
2008020105
2008120106 return default_value;
@@ -20137,7 +20162,7 @@ class basic_json
2013720162 @since version 2.0.2
2013820163 */
2013920164 template<class ValueType, typename std::enable_if<
20140- std::is_convertible <basic_json_t, ValueType>::value, int>::type = 0>
20165+ detail::is_getable <basic_json_t, ValueType>::value, int>::type = 0>
2014120166 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
2014220167 {
2014320168 // at only works for objects
@@ -20146,7 +20171,7 @@ class basic_json
2014620171 // if pointer resolves a value, return it or use default value
2014720172 JSON_TRY
2014820173 {
20149- return ptr.get_checked(this);
20174+ return ptr.get_checked(this).template get<ValueType>() ;
2015020175 }
2015120176 JSON_INTERNAL_CATCH (out_of_range&)
2015220177 {
@@ -24620,8 +24645,8 @@ class basic_json
2462024645 }
2462124646
2462224647 // collect mandatory members
24623- const std::string op = get_value("op", "op", true);
24624- const std::string path = get_value(op, "path", true);
24648+ const auto op = get_value("op", "op", true).template get<std::string>( );
24649+ const auto path = get_value(op, "path", true).template get<std::string>( );
2462524650 json_pointer ptr(path);
2462624651
2462724652 switch (get_op(op))
@@ -24647,7 +24672,7 @@ class basic_json
2464724672
2464824673 case patch_operations::move:
2464924674 {
24650- const std::string from_path = get_value("move", "from", true);
24675+ const auto from_path = get_value("move", "from", true).template get<std::string>( );
2465124676 json_pointer from_ptr(from_path);
2465224677
2465324678 // the "from" location must exist - use at()
@@ -24664,7 +24689,7 @@ class basic_json
2466424689
2466524690 case patch_operations::copy:
2466624691 {
24667- const std::string from_path = get_value("copy", "from", true);
24692+ const auto from_path = get_value("copy", "from", true).template get<std::string>( );
2466824693 const json_pointer from_ptr(from_path);
2466924694
2467024695 // the "from" location must exist - use at()
@@ -25086,6 +25111,7 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std
2508625111#undef JSON_HAS_CPP_17
2508725112#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
2508825113#undef NLOHMANN_BASIC_JSON_TPL
25114+ #undef JSON_EXPLICIT
2508925115
2509025116// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
2509125117#undef JSON_HEDLEY_ALWAYS_INLINE
0 commit comments