This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libstdc++/83981] vector::resize(size_type) should not require T to be CopyInsertable when std=c++14


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83981

--- Comment #14 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Daniel Krügler from comment #11)
> (In reply to Jonathan Wakely from comment #10)
> > Perhaps Daniel can comment, since he wrote the resolution of lwg 2033.
> > 
> > Daniel, if the intent was that vector::resize(size_type) must only move,
> > even if that can throw, why is the exception-safety guarantee worded in
> > terms of a non-CopyInsertable condition? Was the intention really to forbid
> > implementations from giving the strong exception-safety guarantee (by
> > copying) if possible?
> 
> I'm in the mid of something else, so forgive me if I'm still catching up.
> The wording was slightly changed by LWG 2323 later on, does that clarify?

No, that doesn't change the part I'm asking about.

> [If not, I can look deeper into it tomorrow evening, so please let me know]
> The basic idea that the original wording tried to ensure is that strong
> exception-safety holds for non-throwing move-only types or copyable types,
> because that was the original intend suggested by Howard Hinnant.

Right, that was my understanding too. The current wording doesn't say that,
because (as Daniel T. explains) by only requiring MoveInsertable it seems to
forbid doing copy-insertion when the move might throw, and therefore providing
the strong guarantee by copying is forbidden.

(In reply to Daniel Trebbien from comment #12)
> https://wg21.link/lwg2158 looks relevant, particularly this part:
> 
> "This requirement is not sufficient if an implementation is free to select
> copy constructor when !is_nothrow_move_constructible<T>::value &&
> is_copy_constructible<T>::value evaluates to true. Unfortunately,
> is_copy_constructible cannot reliably determine whether T is really
> copy-constructible. A class may contain public non-deleted copy constructor
> whose definition does not exist or cannot be instantiated successfully
> (e.g., std::vector<std::unique_ptr<int>> has copy constructor, but this type
> is not copy-constructible)."

Ah yes, that's *exactly* the problem. We need to be allowed to copy when that
would work, but in general we can't tell if copying will work because
is_copy_constructible doesn't always tell us the right answer.

(And also, is_copy_constructible isn't the right trait because the allocator
could inject different arguments in the construct call, but that's the separate
issue I mentioned in comment 10).

> Even though is_copy_constructible for std::vector<std::unique_ptr<...>> is
> true, resizing a vector of this element type works because the std::vector
> move constructor is noexcept, so the move constructor is selected.
> 
> Jonathan, I personally think that your argument in Comment 10 is persuasive.
> 
> Further, I like the suggestion in LWG 2158 to add "if
> !is_nothrow_move_constructible<T>::value && is_copy_constructible<T>::value
> then T shall be CopyInsertable into *this;" to the requirements of
> vector::resize(size_type). I think that this would be required because,
> based on my reading of [temp.inst], it is a well-formed program to
> instantiate boost::optional<NonCopyConstructibleType>, as this does not
> require the instantiation of the boost::optional<NonCopyConstructibleType>
> copy constructor.

Agreed. This would mean that it's the author of the std::vector value_type who
must be responsible for ensuring that the type really is copyable if the traits
cause std::vector to try and copy it (i.e. it is a boost::optional bug, for
having a noexcept(false) move constructor and a copy constructor that is always
declared but might be ill-formed when instantiated).

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]