re PR libstdc++/87855 (std::optional<T> only copy-constructible if T is trivially copy-constructible)
PR libstdc++/87855 Also implement P0602R4 (variant and optional should propagate copy/move triviality) for std::optional. * include/std/optional (_Optional_payload): Change the main constraints to check constructibility in addition to assignability. (operator=): Make constexpr. (_M_reset): Likewise. (_M_construct): Likewise. (operator->): Likewise. * testsuite/20_util/optional/assignment/8.cc: Adjust. * testsuite/20_util/optional/assignment/9.cc: New. From-SVN: r266278
This commit is contained in:
parent
f615cb162d
commit
4fea820523
|
@ -1,3 +1,18 @@
|
||||||
|
2018-11-19 Ville Voutilainen <ville.voutilainen@gmail.com>
|
||||||
|
|
||||||
|
PR libstdc++/87855
|
||||||
|
Also implement P0602R4 (variant and optional
|
||||||
|
should propagate copy/move triviality) for std::optional.
|
||||||
|
* include/std/optional (_Optional_payload): Change
|
||||||
|
the main constraints to check constructibility in
|
||||||
|
addition to assignability.
|
||||||
|
(operator=): Make constexpr.
|
||||||
|
(_M_reset): Likewise.
|
||||||
|
(_M_construct): Likewise.
|
||||||
|
(operator->): Likewise.
|
||||||
|
* testsuite/20_util/optional/assignment/8.cc: Adjust.
|
||||||
|
* testsuite/20_util/optional/assignment/9.cc: New.
|
||||||
|
|
||||||
2018-11-19 Jonathan Wakely <jwakely@redhat.com>
|
2018-11-19 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
PR libstdc++/88084 - Implement LWG 2777
|
PR libstdc++/88084 - Implement LWG 2777
|
||||||
|
|
|
@ -103,10 +103,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template <typename _Tp,
|
template <typename _Tp,
|
||||||
bool /*_HasTrivialDestructor*/ =
|
bool /*_HasTrivialDestructor*/ =
|
||||||
is_trivially_destructible_v<_Tp>,
|
is_trivially_destructible_v<_Tp>,
|
||||||
bool /*_HasTrivialCopyAssignment*/ =
|
bool /*_HasTrivialCopy */ =
|
||||||
is_trivially_copy_assignable_v<_Tp>,
|
is_trivially_copy_assignable_v<_Tp>
|
||||||
bool /*_HasTrivialMoveAssignment*/ =
|
&& is_trivially_copy_constructible_v<_Tp>,
|
||||||
is_trivially_move_assignable_v<_Tp>>
|
bool /*_HasTrivialMove */ =
|
||||||
|
is_trivially_move_assignable_v<_Tp>
|
||||||
|
&& is_trivially_move_constructible_v<_Tp>>
|
||||||
struct _Optional_payload
|
struct _Optional_payload
|
||||||
{
|
{
|
||||||
constexpr _Optional_payload() noexcept : _M_empty() { }
|
constexpr _Optional_payload() noexcept : _M_empty() { }
|
||||||
|
@ -148,6 +150,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
this->_M_construct(std::move(__other._M_payload));
|
this->_M_construct(std::move(__other._M_payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr
|
||||||
_Optional_payload&
|
_Optional_payload&
|
||||||
operator=(const _Optional_payload& __other)
|
operator=(const _Optional_payload& __other)
|
||||||
{
|
{
|
||||||
|
@ -163,6 +166,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr
|
||||||
_Optional_payload&
|
_Optional_payload&
|
||||||
operator=(_Optional_payload&& __other)
|
operator=(_Optional_payload&& __other)
|
||||||
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
|
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
|
||||||
|
@ -216,6 +220,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ return this->_M_payload; }
|
{ return this->_M_payload; }
|
||||||
|
|
||||||
// _M_reset is a 'safe' operation with no precondition.
|
// _M_reset is a 'safe' operation with no precondition.
|
||||||
|
constexpr
|
||||||
void
|
void
|
||||||
_M_reset() noexcept
|
_M_reset() noexcept
|
||||||
{
|
{
|
||||||
|
@ -346,6 +351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_Optional_payload(const _Optional_payload&) = default;
|
_Optional_payload(const _Optional_payload&) = default;
|
||||||
_Optional_payload(_Optional_payload&&) = default;
|
_Optional_payload(_Optional_payload&&) = default;
|
||||||
|
|
||||||
|
constexpr
|
||||||
_Optional_payload&
|
_Optional_payload&
|
||||||
operator=(const _Optional_payload& __other)
|
operator=(const _Optional_payload& __other)
|
||||||
{
|
{
|
||||||
|
@ -394,6 +400,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ return this->_M_payload; }
|
{ return this->_M_payload; }
|
||||||
|
|
||||||
// _M_reset is a 'safe' operation with no precondition.
|
// _M_reset is a 'safe' operation with no precondition.
|
||||||
|
constexpr
|
||||||
void
|
void
|
||||||
_M_reset() noexcept
|
_M_reset() noexcept
|
||||||
{
|
{
|
||||||
|
@ -466,6 +473,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_Optional_payload&
|
_Optional_payload&
|
||||||
operator=(const _Optional_payload& __other) = default;
|
operator=(const _Optional_payload& __other) = default;
|
||||||
|
|
||||||
|
constexpr
|
||||||
_Optional_payload&
|
_Optional_payload&
|
||||||
operator=(_Optional_payload&& __other)
|
operator=(_Optional_payload&& __other)
|
||||||
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
|
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
|
||||||
|
@ -513,6 +521,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ return this->_M_payload; }
|
{ return this->_M_payload; }
|
||||||
|
|
||||||
// _M_reset is a 'safe' operation with no precondition.
|
// _M_reset is a 'safe' operation with no precondition.
|
||||||
|
constexpr
|
||||||
void
|
void
|
||||||
_M_reset() noexcept
|
_M_reset() noexcept
|
||||||
{
|
{
|
||||||
|
@ -581,6 +590,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_Optional_payload(const _Optional_payload&) = default;
|
_Optional_payload(const _Optional_payload&) = default;
|
||||||
_Optional_payload(_Optional_payload&&) = default;
|
_Optional_payload(_Optional_payload&&) = default;
|
||||||
|
|
||||||
|
constexpr
|
||||||
_Optional_payload&
|
_Optional_payload&
|
||||||
operator=(const _Optional_payload& __other)
|
operator=(const _Optional_payload& __other)
|
||||||
{
|
{
|
||||||
|
@ -596,6 +606,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr
|
||||||
_Optional_payload&
|
_Optional_payload&
|
||||||
operator=(_Optional_payload&& __other)
|
operator=(_Optional_payload&& __other)
|
||||||
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
|
noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
|
||||||
|
@ -624,6 +635,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
bool _M_engaged;
|
bool _M_engaged;
|
||||||
|
|
||||||
template<typename... _Args>
|
template<typename... _Args>
|
||||||
|
constexpr
|
||||||
void
|
void
|
||||||
_M_construct(_Args&&... __args)
|
_M_construct(_Args&&... __args)
|
||||||
noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
|
noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>)
|
||||||
|
@ -643,6 +655,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ return this->_M_payload; }
|
{ return this->_M_payload; }
|
||||||
|
|
||||||
// _M_reset is a 'safe' operation with no precondition.
|
// _M_reset is a 'safe' operation with no precondition.
|
||||||
|
constexpr
|
||||||
void
|
void
|
||||||
_M_reset() noexcept
|
_M_reset() noexcept
|
||||||
{
|
{
|
||||||
|
@ -681,6 +694,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
// _M_reset is a 'safe' operation with no precondition.
|
// _M_reset is a 'safe' operation with no precondition.
|
||||||
|
constexpr
|
||||||
void
|
void
|
||||||
_M_reset() noexcept
|
_M_reset() noexcept
|
||||||
{
|
{
|
||||||
|
@ -1217,6 +1231,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
operator->() const
|
operator->() const
|
||||||
{ return std::__addressof(this->_M_get()); }
|
{ return std::__addressof(this->_M_get()); }
|
||||||
|
|
||||||
|
constexpr
|
||||||
_Tp*
|
_Tp*
|
||||||
operator->()
|
operator->()
|
||||||
{ return std::__addressof(this->_M_get()); }
|
{ return std::__addressof(this->_M_get()); }
|
||||||
|
|
|
@ -91,6 +91,24 @@ struct S2 {
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivially_move_assignable_v<S2>);
|
static_assert(std::is_trivially_move_assignable_v<S2>);
|
||||||
|
|
||||||
|
struct S3 {
|
||||||
|
S3(const S3&);
|
||||||
|
S3& operator=(const S3&) = default;
|
||||||
|
};
|
||||||
|
static_assert(std::is_trivially_copy_assignable_v<S3>);
|
||||||
|
static_assert(std::is_copy_assignable_v<S3>);
|
||||||
|
static_assert(!std::is_trivially_copy_assignable_v<std::optional<S3>>);
|
||||||
|
static_assert(std::is_copy_assignable_v<std::optional<S3>>);
|
||||||
|
|
||||||
|
struct S4 {
|
||||||
|
S4(S4&&);
|
||||||
|
S4& operator=(S4&&) = default;
|
||||||
|
};
|
||||||
|
static_assert(std::is_trivially_move_assignable_v<S4>);
|
||||||
|
static_assert(std::is_move_assignable_v<S4>);
|
||||||
|
static_assert(!std::is_trivially_move_assignable_v<std::optional<S4>>);
|
||||||
|
static_assert(std::is_move_assignable_v<std::optional<S4>>);
|
||||||
|
|
||||||
union U2 {
|
union U2 {
|
||||||
char dummy;
|
char dummy;
|
||||||
S2 s;
|
S2 s;
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
// { dg-options "-std=gnu++17" }
|
||||||
|
// { dg-do compile { target c++17 } }
|
||||||
|
|
||||||
|
// Copyright (C) 2018 Free Software Foundation, Inc.
|
||||||
|
//
|
||||||
|
// This file is part of the GNU ISO C++ Library. This library is free
|
||||||
|
// software; you can redistribute it and/or modify it under the
|
||||||
|
// terms of the GNU General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 3, or (at your option)
|
||||||
|
// any later version.
|
||||||
|
|
||||||
|
// This library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this library; see the file COPYING3. If not see
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
constexpr bool f()
|
||||||
|
{
|
||||||
|
std::optional<int> o1{42};
|
||||||
|
std::optional<int> o2;
|
||||||
|
o2 = o1;
|
||||||
|
return (o1 == o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool f2()
|
||||||
|
{
|
||||||
|
std::optional<int> o1{42};
|
||||||
|
std::optional<int> o2;
|
||||||
|
std::optional<int> o3;
|
||||||
|
o2 = o1;
|
||||||
|
o3 = std::move(o2);
|
||||||
|
return (o1 == o3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g()
|
||||||
|
{
|
||||||
|
constexpr bool b = f();
|
||||||
|
static_assert(b);
|
||||||
|
constexpr bool b2 = f2();
|
||||||
|
static_assert(b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NonTrivialButConstexpr
|
||||||
|
{
|
||||||
|
int dummy;
|
||||||
|
NonTrivialButConstexpr() = default;
|
||||||
|
constexpr NonTrivialButConstexpr(int val) : dummy(val) {}
|
||||||
|
NonTrivialButConstexpr(const NonTrivialButConstexpr&) = default;
|
||||||
|
NonTrivialButConstexpr(NonTrivialButConstexpr&&) = default;
|
||||||
|
constexpr NonTrivialButConstexpr&
|
||||||
|
operator=(const NonTrivialButConstexpr& other)
|
||||||
|
{
|
||||||
|
dummy = other.dummy;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
constexpr NonTrivialButConstexpr&
|
||||||
|
operator=(NonTrivialButConstexpr&& other)
|
||||||
|
{
|
||||||
|
dummy = other.dummy;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr bool f3()
|
||||||
|
{
|
||||||
|
std::optional<NonTrivialButConstexpr> d1, d2;
|
||||||
|
d1 = d2;
|
||||||
|
std::optional<NonTrivialButConstexpr> o1{42};
|
||||||
|
std::optional<NonTrivialButConstexpr> o2{22};
|
||||||
|
o2 = o1;
|
||||||
|
return ((*o1).dummy == (*o2).dummy && o1->dummy == o2->dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool f4()
|
||||||
|
{
|
||||||
|
std::optional<NonTrivialButConstexpr> d1, d2;
|
||||||
|
d1 = std::move(d2);
|
||||||
|
std::optional<NonTrivialButConstexpr> o1{42};
|
||||||
|
std::optional<NonTrivialButConstexpr> o2{22};
|
||||||
|
std::optional<NonTrivialButConstexpr> o3{33};
|
||||||
|
o2 = o1;
|
||||||
|
o3 = std::move(o2);
|
||||||
|
return ((*o1).dummy == (*o3).dummy && o1->dummy == o3->dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void g2()
|
||||||
|
{
|
||||||
|
constexpr bool b = f3();
|
||||||
|
static_assert(b);
|
||||||
|
constexpr bool b2 = f4();
|
||||||
|
static_assert(b2);
|
||||||
|
}
|
Loading…
Reference in New Issue