From a00c90bbae7f8efd4365d8c5a7d75efec197e027 Mon Sep 17 00:00:00 2001 From: Dmitry Arkhipov Date: Fri, 21 Jul 2023 18:03:38 +0300 Subject: [PATCH] fix inconsistent choice of init list constructor On some compilers value{x} invokes initializer_list constructor, on others it is equivalent to value(x). This is very problematic, but this isn't something we can fix. On the other hand, we CAN make init list construction to be equivalent to value(x), if the size of init list is one. This commit does exactly that. --- include/boost/json/impl/value.ipp | 12 +++++++++++- include/boost/json/value.hpp | 15 ++++++++++----- test/value.cpp | 9 +++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/include/boost/json/impl/value.ipp b/include/boost/json/impl/value.ipp index b4e80f036..f8887cb2f 100644 --- a/include/boost/json/impl/value.ipp +++ b/include/boost/json/impl/value.ipp @@ -231,13 +231,23 @@ value( storage_ptr sp) { if(value_ref::maybe_object(init)) + { ::new(&obj_) object( value_ref::make_object( init, std::move(sp))); - else + } + else if( init.size() != 1 ) + { ::new(&arr_) array( value_ref::make_array( init, std::move(sp))); + } + else + { + ::new(&sca_) scalar(); + value temp = init.begin()->make_value( std::move(sp) ); + swap(temp); + } } //---------------------------------------------------------- diff --git a/include/boost/json/value.hpp b/include/boost/json/value.hpp index 24df80a7e..cd803ba6e 100644 --- a/include/boost/json/value.hpp +++ b/include/boost/json/value.hpp @@ -1014,11 +1014,16 @@ class value /** Construct from an initializer-list - If the initializer list consists of key/value - pairs, an @ref object is created. Otherwise - an @ref array is created. The contents of the - initializer list are copied to the newly constructed - value using the specified memory resource. + @li If the initializer list consists of key/value + pairs, an @ref object is created; otherwise, + + @li if the size of the initializer list is exactly 1, the object is + constructed directly from that sole element; otherwise, + + @li an @ref array is created. + + The contents of the initializer list are copied to the newly + constructed value using the specified memory resource. @par Complexity Linear in `init.size()`. diff --git a/test/value.cpp b/test/value.cpp index 66ce1c6f7..5d71a16a8 100644 --- a/test/value.cpp +++ b/test/value.cpp @@ -2131,6 +2131,15 @@ class value_test void testInitList() { + { + value jv{}; + BOOST_TEST( jv.is_null() ); + } + { + value jv{0}; + BOOST_TEST( jv == 0 ); + } + check_array(value{0,0,0}, 0, 0, 0); check_array(value{false,false,false}, false, false, false); check_array(value{false,2,false}, false, 2, false);