Date: Thu, 9 Sep 2021 09:02:11 +0200
Am Do., 9. Sept. 2021 um 06:59 Uhr schrieb Jason McKesson via Std-Proposals
<std-proposals_at_[hidden]>:
> On Wed, Sep 8, 2021 at 2:29 PM D'Alessandro, Luke K via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> >
> >
> > I guess I have two questions:
> >
> > 1. Does std::construct_at change the active member of a union?
>
> As stated in [class.union]/2, "a non-static data member is active if
> its name refers to an object whose lifetime has begun and has not
> ended." `construct_at` can begin the lifetime of objects (which can
> also cause the lifetime of other overlapping objects to end).
>
> Therefore, it can change the active union member.
>
While `std::construct_at` does indeed begin the lifetime of the element it
constructs, the lifetime of the array has not begun. Therefore, forming a
reference to an object outside of its lifetime is UB, so `&u.data[1]` is
not possible. We had the exact same issue recently when implementing
constexpr std::string for MSVC STL. There we have an indirection to
`char_traits` and would need to call `char_traits::assign(&sso_storage[0],
CharType())` which again is invalid due to forming of the reference to
`sso_storage[0]` outside of its lifetime
If you have a non-assignable class then the best way around is an
`
if constexpr(std::is_assignable_v) {
// change the active member of the union to the array here.
}
std::construct_at(...)
`
Cheers
Michael
<std-proposals_at_[hidden]>:
> On Wed, Sep 8, 2021 at 2:29 PM D'Alessandro, Luke K via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> >
> >
> > I guess I have two questions:
> >
> > 1. Does std::construct_at change the active member of a union?
>
> As stated in [class.union]/2, "a non-static data member is active if
> its name refers to an object whose lifetime has begun and has not
> ended." `construct_at` can begin the lifetime of objects (which can
> also cause the lifetime of other overlapping objects to end).
>
> Therefore, it can change the active union member.
>
While `std::construct_at` does indeed begin the lifetime of the element it
constructs, the lifetime of the array has not begun. Therefore, forming a
reference to an object outside of its lifetime is UB, so `&u.data[1]` is
not possible. We had the exact same issue recently when implementing
constexpr std::string for MSVC STL. There we have an indirection to
`char_traits` and would need to call `char_traits::assign(&sso_storage[0],
CharType())` which again is invalid due to forming of the reference to
`sso_storage[0]` outside of its lifetime
If you have a non-assignable class then the best way around is an
`
if constexpr(std::is_assignable_v) {
// change the active member of the union to the array here.
}
std::construct_at(...)
`
Cheers
Michael
Received on 2021-09-09 02:02:29