Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix inconsistent choice of init list constructor #921

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions include/boost/json/impl/value.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,28 @@ value(
storage_ptr sp)
{
if(value_ref::maybe_object(init))
{
::new(&obj_) object(
value_ref::make_object(
init, std::move(sp)));
}
else
::new(&arr_) array(
value_ref::make_array(
init, std::move(sp)));
{
#ifndef BOOST_JSON_LEGACY_INIT_LIST_BEHAVIOR
if( init.size() == 1 )
{
::new(&sca_) scalar();
value temp = init.begin()->make_value( std::move(sp) );
swap(temp);
}
else
#endif
{
::new(&arr_) array(
value_ref::make_array(
init, std::move(sp)));
}
}
}

//----------------------------------------------------------
Expand Down
29 changes: 24 additions & 5 deletions include/boost/json/value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()`.
Expand All @@ -1032,6 +1037,20 @@ class value
@param sp A pointer to the @ref memory_resource
to use. The container will acquire shared
ownership of the memory resource.
@par Note
The previous behavior of this constructor was to always
construct either an @ref object or an @ref array. In practice though,
several C++ implementations did not treat `value{x}` as a constructor
from initializer list. This effectively resulted in different behavior
on different implementations. <br>
If you need the legacy behavior define macro
`BOOST_JSON_LEGACY_INIT_LIST_BEHAVIOR` when you are building the
library. The macro and the functionality will be deprecated in the
future and then removed, so we urge you to change your code for the new
behavior as soon as possible. The simplest way to create an @ref array
with 1 element using an initializer list is via `array{x}`.
*/
BOOST_JSON_DECL
value(
Expand Down
11 changes: 11 additions & 0 deletions test/value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,17 @@ class value_test
void
testInitList()
{
{
value jv{};
BOOST_TEST( jv.is_null() );
}
#ifndef BOOST_JSON_LEGACY_INIT_LIST_BEHAVIOR
{
value jv{0};
BOOST_TEST( jv == 0 );
}
#endif

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);
Expand Down
Loading