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

Conversation

grisumbras
Copy link
Member

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.

Fix #920

@cppalliance-bot
Copy link

@grisumbras grisumbras force-pushed the fix/inconsistent-init-list-behavior branch from 8f6a3c8 to c854e44 Compare July 21, 2023 16:54
@codecov
Copy link

codecov bot commented Jul 21, 2023

Codecov Report

Merging #921 (25e740d) into develop (2acdb29) will increase coverage by 0.00%.
The diff coverage is 100.00%.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           develop     #921   +/-   ##
========================================
  Coverage    92.95%   92.96%           
========================================
  Files           85       85           
  Lines         8052     8056    +4     
========================================
+ Hits          7485     7489    +4     
  Misses         567      567           
Files Changed Coverage Δ
include/boost/json/value.hpp 98.92% <ø> (ø)
include/boost/json/impl/value.ipp 100.00% <100.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2acdb29...25e740d. Read the comment docs.

@vinniefalco
Copy link
Member

Hey good idea !

@cppalliance-bot
Copy link

@nkolotov
Copy link

¿What if caller actually wants to produce an array with a single item? Some people may already be using code that supplies initializer_list explicitly expecting array to be produced.

void Pack(::std::initializer_list<::boost::json::value_ref> items)
{
    ::boost::json::value json{items};
    ::boost::json::array & array{json.as_array()};
    // do something with array...
}

And proposed change will break this code when only a single item is supplied.

Also i'm not sure about ::new(this) value (.... ¿Is an attempt to reuse storage of the object which lifetime hasn't started yet a well-defined behavior? ¿Will access to newly created object through reference to the old one be valid?

@grisumbras
Copy link
Member Author

The proposed change is the only way I could come up with that would make the behaviour consistent. The problem of behaviour being inconsistent between compilers have been haunting us for years.

That being said, creating an array from one element init list is very easy:

std::initializer_list<value_ref> items = {x};
value jv = array(items);

or

value jv = array{x};

@grisumbras
Copy link
Member Author

Also i'm not sure about ::new(this) value (.... ¿Is an attempt to reuse storage of the object which lifetime hasn't started yet a well-defined behavior? ¿Will access to newly created object through reference to the old one be valid?

How could there be a reference to an object that does not exist yet?

@nkolotov
Copy link

nkolotov commented Jul 26, 2023

The proposed change is the only way I could come up with that would make the behaviour consistent.

However you make behavior of constructor taking initializer_list inconsistent. Potentially breaking existing code.

How could there be a reference to an object that does not exist yet?

In case if ::new(this), this is a pointer to the object being currently constructed. And if object here turns out to be not transparently replaceable then this pointer as well as any other names referring to the current object will become invalid. Also even if object is transparently replaceable, ::new(this) is dangerous in other ways since ::boost::json::value is not trivially destructible type.

@grisumbras
Copy link
Member Author

However you make behavior of constructor taking initializer_list inconsistent. Potentially breaking existing code.

No, it will not make it inconsistent. It will be consistent with documented behaviour (which reminds me that I should have amended documentation). And yes, it will break existing code. So, I'm leaning towards temporary providing a macro to disable the new behaviour.

In case if ::new(this), this is a pointer to the object being currently constructed. And if object here turns out to be not transparently replaceable then this pointer as well as any other names referring to the current object will become invalid. Also even if object is transparently replaceable, ::new(this) is dangerous in other ways since ::boost::json::value is not trivially destructible type.

Ok, just to be sure I will replace new(this) with a different implementation.

@grisumbras grisumbras force-pushed the fix/inconsistent-init-list-behavior branch from c854e44 to 31400c9 Compare August 1, 2023 16:24
@cppalliance-bot
Copy link

@grisumbras grisumbras force-pushed the fix/inconsistent-init-list-behavior branch from 31400c9 to a00c90b Compare August 23, 2023 16:50
@cppalliance-bot
Copy link

@grisumbras grisumbras force-pushed the fix/inconsistent-init-list-behavior branch from a00c90b to 85df13d Compare August 23, 2023 19:41
@cppalliance-bot
Copy link

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.
@grisumbras grisumbras force-pushed the fix/inconsistent-init-list-behavior branch from 85df13d to 25e740d Compare August 25, 2023 17:28
@grisumbras grisumbras merged commit 25e740d into boostorg:develop Aug 25, 2023
4 checks passed
@grisumbras grisumbras deleted the fix/inconsistent-init-list-behavior branch August 25, 2023 17:54
@cppalliance-bot
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

value constructor behaviour inconsistent across compilers (initializer_list)
4 participants