libstdc++: Simplify std::optional::value()

The structure of these functions likely dates from the time before G++
fully supported C++14 extended constexpr, so that the throw expression
had to be the operand of a conditional expression. That is not true now,
so we can use a more straightforward version of the code.

We can also simplify the declaration of __throw_bad_optional_access by
using the C++11-style [[noreturn]] attribute so that a separate
declaration isn't needed.

libstdc++-v3/ChangeLog:

	* include/experimental/optional (__throw_bad_optional_access):
	Replace GNU attribute with C++11 attribute.
	(optional::value, optional::value_or): Use if statements
	instead of conditional expressions.
	* include/std/optional (__throw_bad_optional_access)
	(optional::value, optional::value_or): Likewise.
This commit is contained in:
Jonathan Wakely 2021-07-27 14:50:28 +01:00
parent b7195fb01f
commit 9360d6cd17
2 changed files with 46 additions and 53 deletions

View File

@ -114,12 +114,8 @@ inline namespace fundamentals_v1
/// @cond undocumented
void
__throw_bad_optional_access(const char*)
__attribute__((__noreturn__));
// XXX Does not belong here.
inline void
[[noreturn]] inline void
__throw_bad_optional_access(const char* __s)
{ _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
@ -674,41 +670,37 @@ inline namespace fundamentals_v1
constexpr const _Tp&
value() const&
{
return this->_M_is_engaged()
? this->_M_get()
: (__throw_bad_optional_access("Attempt to access value of a "
"disengaged optional object"),
this->_M_get());
if (this->_M_is_engaged())
return this->_M_get();
__throw_bad_optional_access("Attempt to access value of a "
"disengaged optional object");
}
constexpr _Tp&
value()&
{
return this->_M_is_engaged()
? this->_M_get()
: (__throw_bad_optional_access("Attempt to access value of a "
"disengaged optional object"),
this->_M_get());
if (this->_M_is_engaged())
return this->_M_get();
__throw_bad_optional_access("Attempt to access value of a "
"disengaged optional object");
}
constexpr _Tp&&
value()&&
{
return this->_M_is_engaged()
? std::move(this->_M_get())
: (__throw_bad_optional_access("Attempt to access value of a "
"disengaged optional object"),
std::move(this->_M_get()));
if (this->_M_is_engaged())
return std::move(this->_M_get());
__throw_bad_optional_access("Attempt to access value of a "
"disengaged optional object");
}
constexpr const _Tp&&
value() const&&
{
return this->_M_is_engaged()
? std::move(this->_M_get())
: (__throw_bad_optional_access("Attempt to access value of a "
"disengaged optional object"),
std::move(this->_M_get()));
if (this->_M_is_engaged())
return std::move(this->_M_get());
__throw_bad_optional_access("Attempt to access value of a "
"disengaged optional object");
}
template<typename _Up>
@ -719,9 +711,10 @@ inline namespace fundamentals_v1
is_convertible<_Up&&, _Tp>>(),
"Cannot return value");
return this->_M_is_engaged()
? this->_M_get()
: static_cast<_Tp>(std::forward<_Up>(__u));
if (this->_M_is_engaged())
return this->_M_get();
else
return static_cast<_Tp>(std::forward<_Up>(__u));
}
template<typename _Up>
@ -732,9 +725,10 @@ inline namespace fundamentals_v1
is_convertible<_Up&&, _Tp>>(),
"Cannot return value" );
return this->_M_is_engaged()
? std::move(this->_M_get())
: static_cast<_Tp>(std::forward<_Up>(__u));
if (this->_M_is_engaged())
return std::move(this->_M_get());
else
return static_cast<_Tp>(std::forward<_Up>(__u));
}
};

View File

@ -91,12 +91,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return "bad optional access"; }
};
void
__throw_bad_optional_access()
__attribute__((__noreturn__));
// XXX Does not belong here.
inline void
[[__noreturn__]] inline void
__throw_bad_optional_access()
{ _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); }
@ -943,33 +939,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr const _Tp&
value() const&
{
return this->_M_is_engaged()
? this->_M_get()
: (__throw_bad_optional_access(), this->_M_get());
if (this->_M_is_engaged())
return this->_M_get();
__throw_bad_optional_access();
}
constexpr _Tp&
value()&
{
return this->_M_is_engaged()
? this->_M_get()
: (__throw_bad_optional_access(), this->_M_get());
if (this->_M_is_engaged())
return this->_M_get();
__throw_bad_optional_access();
}
constexpr _Tp&&
value()&&
{
return this->_M_is_engaged()
? std::move(this->_M_get())
: (__throw_bad_optional_access(), std::move(this->_M_get()));
if (this->_M_is_engaged())
return std::move(this->_M_get());
__throw_bad_optional_access();
}
constexpr const _Tp&&
value() const&&
{
return this->_M_is_engaged()
? std::move(this->_M_get())
: (__throw_bad_optional_access(), std::move(this->_M_get()));
if (this->_M_is_engaged())
return std::move(this->_M_get());
__throw_bad_optional_access();
}
template<typename _Up>
@ -979,8 +975,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(is_copy_constructible_v<_Tp>);
static_assert(is_convertible_v<_Up&&, _Tp>);
return this->_M_is_engaged()
? this->_M_get() : static_cast<_Tp>(std::forward<_Up>(__u));
if (this->_M_is_engaged())
return this->_M_get();
else
return static_cast<_Tp>(std::forward<_Up>(__u));
}
template<typename _Up>
@ -990,9 +988,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(is_move_constructible_v<_Tp>);
static_assert(is_convertible_v<_Up&&, _Tp>);
return this->_M_is_engaged()
? std::move(this->_M_get())
: static_cast<_Tp>(std::forward<_Up>(__u));
if (this->_M_is_engaged())
return std::move(this->_M_get());
else
return static_cast<_Tp>(std::forward<_Up>(__u));
}
void reset() noexcept { this->_M_reset(); }