Implement P0307R2, Making Optional Greater Equal Again.
* include/experimental/optional (_Has_addressof): Fix the comment. * include/std/optional (_Has_addressof): Likewise. (operator=(_Up&&)): Constrain. (operator=(const optional<_Up>&)): Likewise. (operator=(optional<_Up>&&)): Likewise. (__optional_relop_t): New. (operator==(const optional<_Tp>&, const optional<_Tp>&)): Constrain. (operator!=(const optional<_Tp>&, const optional<_Tp>&)): Constrain and make transparent. (operator<(const optional<_Tp>&, const optional<_Tp>&)): Constrain. (operator>(const optional<_Tp>&, const optional<_Tp>&)): Constrain and make transparent. (operator<=(const optional<_Tp>&, const optional<_Tp>&)): Likewise. (operator>=(const optional<_Tp>&, const optional<_Tp>&)): Likewise. (operator==(const optional<_Tp>&, const _Tp&): Constrain. (operator==(const _Tp&, const optional<_Tp>&)): Likewise. (operator!=(const optional<_Tp>&, _Tp const&)): Constrain and make transparent. (operator!=(const _Tp&, const optional<_Tp>&)): Likewise. (operator<(const optional<_Tp>&, const _Tp&)): Constrain. (operator<(const _Tp&, const optional<_Tp>&)): Likewise. (operator>(const optional<_Tp>&, const _Tp&)): Constrain and make transparent. (operator>(const _Tp&, const optional<_Tp>&)): Likewise. (operator<=(const optional<_Tp>&, const _Tp&)): Likewise. (operator<=(const _Tp&, const optional<_Tp>&)): Likewise. (operator>=(const optional<_Tp>&, const _Tp&)): Likewise. (operator>=(const _Tp&, const optional<_Tp>&)): Likewise. * testsuite/20_util/optional/constexpr/relops/2.cc: Adjust. * testsuite/20_util/optional/constexpr/relops/4.cc: Likewise. * testsuite/20_util/optional/relops/1.cc: Likewise. * testsuite/20_util/optional/relops/2.cc: Likewise. * testsuite/20_util/optional/relops/3.cc: Likewise. * testsuite/20_util/optional/relops/4.cc: Likewise. * testsuite/20_util/optional/requirements.cc: Add tests to verify that optional's relops are transparent and don't synthesize operators. Also test that assignment sfinaes. From-SVN: r238292
This commit is contained in:
parent
ceea48fc64
commit
86c0ec1de1
|
@ -1,3 +1,42 @@
|
|||
Implement P0307R2, Making Optional Greater Equal Again.
|
||||
* include/experimental/optional (_Has_addressof): Fix the comment.
|
||||
* include/std/optional (_Has_addressof): Likewise.
|
||||
(operator=(_Up&&)): Constrain.
|
||||
(operator=(const optional<_Up>&)): Likewise.
|
||||
(operator=(optional<_Up>&&)): Likewise.
|
||||
(__optional_relop_t): New.
|
||||
(operator==(const optional<_Tp>&, const optional<_Tp>&)): Constrain.
|
||||
(operator!=(const optional<_Tp>&, const optional<_Tp>&)):
|
||||
Constrain and make transparent.
|
||||
(operator<(const optional<_Tp>&, const optional<_Tp>&)): Constrain.
|
||||
(operator>(const optional<_Tp>&, const optional<_Tp>&)):
|
||||
Constrain and make transparent.
|
||||
(operator<=(const optional<_Tp>&, const optional<_Tp>&)): Likewise.
|
||||
(operator>=(const optional<_Tp>&, const optional<_Tp>&)): Likewise.
|
||||
(operator==(const optional<_Tp>&, const _Tp&): Constrain.
|
||||
(operator==(const _Tp&, const optional<_Tp>&)): Likewise.
|
||||
(operator!=(const optional<_Tp>&, _Tp const&)):
|
||||
Constrain and make transparent.
|
||||
(operator!=(const _Tp&, const optional<_Tp>&)): Likewise.
|
||||
(operator<(const optional<_Tp>&, const _Tp&)): Constrain.
|
||||
(operator<(const _Tp&, const optional<_Tp>&)): Likewise.
|
||||
(operator>(const optional<_Tp>&, const _Tp&)):
|
||||
Constrain and make transparent.
|
||||
(operator>(const _Tp&, const optional<_Tp>&)): Likewise.
|
||||
(operator<=(const optional<_Tp>&, const _Tp&)): Likewise.
|
||||
(operator<=(const _Tp&, const optional<_Tp>&)): Likewise.
|
||||
(operator>=(const optional<_Tp>&, const _Tp&)): Likewise.
|
||||
(operator>=(const _Tp&, const optional<_Tp>&)): Likewise.
|
||||
* testsuite/20_util/optional/constexpr/relops/2.cc: Adjust.
|
||||
* testsuite/20_util/optional/constexpr/relops/4.cc: Likewise.
|
||||
* testsuite/20_util/optional/relops/1.cc: Likewise.
|
||||
* testsuite/20_util/optional/relops/2.cc: Likewise.
|
||||
* testsuite/20_util/optional/relops/3.cc: Likewise.
|
||||
* testsuite/20_util/optional/relops/4.cc: Likewise.
|
||||
* testsuite/20_util/optional/requirements.cc: Add tests to verify
|
||||
that optional's relops are transparent and don't synthesize
|
||||
operators. Also test that assignment sfinaes.
|
||||
|
||||
2016-07-13 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/bits/basic_string.h [_GLIBCXX_USE_CXX11_ABI] (_M_c_str):
|
||||
|
|
|
@ -155,8 +155,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
* @brief Trait that detects the presence of an overloaded unary operator&.
|
||||
*
|
||||
* Practically speaking this detects the presence of such an operator when
|
||||
* called on a const-qualified lvalue (i.e.
|
||||
* declval<_Tp * const&>().operator&()).
|
||||
* called on a const-qualified lvalue (e.g.
|
||||
* declval<const _Tp&>().operator&()).
|
||||
*/
|
||||
template<typename _Tp>
|
||||
struct _Has_addressof
|
||||
|
|
|
@ -131,8 +131,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
* @brief Trait that detects the presence of an overloaded unary operator&.
|
||||
*
|
||||
* Practically speaking this detects the presence of such an operator when
|
||||
* called on a const-qualified lvalue (i.e.
|
||||
* declval<_Tp * const&>().operator&()).
|
||||
* called on a const-qualified lvalue (e.g.
|
||||
* declval<const _Tp&>().operator&()).
|
||||
*/
|
||||
template<typename _Tp>
|
||||
struct _Has_addressof
|
||||
|
@ -577,16 +577,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Up,
|
||||
enable_if_t<__and_<
|
||||
is_constructible<_Tp, _Up>,
|
||||
is_assignable<_Tp&, _Up>,
|
||||
__not_<is_same<_Up, nullopt_t>>,
|
||||
__not_<__is_optional<_Up>>>::value,
|
||||
bool> = true>
|
||||
optional&
|
||||
operator=(_Up&& __u)
|
||||
{
|
||||
static_assert(__and_<is_constructible<_Tp, _Up>,
|
||||
is_assignable<_Tp&, _Up>>(),
|
||||
"Cannot assign to value type from argument");
|
||||
|
||||
if (this->_M_is_engaged())
|
||||
this->_M_get() = std::forward<_Up>(__u);
|
||||
else
|
||||
|
@ -597,15 +595,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Up,
|
||||
enable_if_t<__and_<
|
||||
__not_<is_same<_Tp, _Up>>>::value,
|
||||
bool> = true>
|
||||
is_constructible<_Tp, _Up>,
|
||||
is_assignable<_Tp&, _Up>,
|
||||
__not_<is_same<_Tp, _Up>>>::value,
|
||||
bool> = true>
|
||||
optional&
|
||||
operator=(const optional<_Up>& __u)
|
||||
{
|
||||
static_assert(__and_<is_constructible<_Tp, _Up>,
|
||||
is_assignable<_Tp&, _Up>>(),
|
||||
"Cannot assign to value type from argument");
|
||||
|
||||
if (__u)
|
||||
{
|
||||
if (this->_M_is_engaged())
|
||||
|
@ -621,16 +617,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
|
||||
template<typename _Up,
|
||||
enable_if_t<__and_<
|
||||
__not_<is_same<_Tp, _Up>>>::value,
|
||||
bool> = true>
|
||||
enable_if_t<__and_<
|
||||
is_constructible<_Tp, _Up>,
|
||||
is_assignable<_Tp&, _Up>,
|
||||
__not_<is_same<_Tp, _Up>>>::value,
|
||||
bool> = true>
|
||||
optional&
|
||||
operator=(optional<_Up>&& __u)
|
||||
{
|
||||
static_assert(__and_<is_constructible<_Tp, _Up>,
|
||||
is_assignable<_Tp&, _Up>>(),
|
||||
"Cannot assign to value type from argument");
|
||||
|
||||
if (__u)
|
||||
{
|
||||
if (this->_M_is_engaged())
|
||||
|
@ -785,41 +779,60 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
}
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
using __optional_relop_t =
|
||||
enable_if_t<is_convertible<_Tp, bool>::value, bool>;
|
||||
|
||||
// [X.Y.8] Comparisons between optional values.
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() == declval<_Tp>())>
|
||||
{
|
||||
return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
|
||||
&& (!__lhs || *__lhs == *__rhs);
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
|
||||
{ return !(__lhs == __rhs); }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() != declval<_Tp>())>
|
||||
{
|
||||
return static_cast<bool>(__lhs) != static_cast<bool>(__rhs)
|
||||
|| (static_cast<bool>(__lhs) && *__lhs != *__rhs);
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() < declval<_Tp>())>
|
||||
{
|
||||
return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs);
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
|
||||
{ return __rhs < __lhs; }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() > declval<_Tp>())>
|
||||
{
|
||||
return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs);
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
|
||||
{ return !(__rhs < __lhs); }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Tp>())>
|
||||
{
|
||||
return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs);
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
|
||||
{ return !(__lhs < __rhs); }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Tp>())>
|
||||
{
|
||||
return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs);
|
||||
}
|
||||
|
||||
// [X.Y.9] Comparisons with nullopt.
|
||||
template<typename _Tp>
|
||||
|
@ -884,64 +897,76 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
// [X.Y.10] Comparisons with value type.
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() == declval<_Tp>())>
|
||||
{ return __lhs && *__lhs == __rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() == declval<_Tp>())>
|
||||
{ return __rhs && __lhs == *__rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs)
|
||||
{ return !__lhs || !(*__lhs == __rhs); }
|
||||
constexpr auto
|
||||
operator!=(const optional<_Tp>& __lhs, const _Tp& __rhs)
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() != declval<_Tp>())>
|
||||
{ return !__lhs || *__lhs != __rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
|
||||
{ return !__rhs || !(__lhs == *__rhs); }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() != declval<_Tp>())>
|
||||
{ return !__rhs || __lhs != *__rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() < declval<_Tp>())>
|
||||
{ return !__lhs || *__lhs < __rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() < declval<_Tp>())>
|
||||
{ return __rhs && __lhs < *__rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
|
||||
{ return __lhs && __rhs < *__lhs; }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() > declval<_Tp>())>
|
||||
{ return __lhs && *__lhs > __rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
|
||||
{ return !__rhs || *__rhs < __lhs; }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() > declval<_Tp>())>
|
||||
{ return !__rhs || __lhs > *__rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
|
||||
{ return !__lhs || !(__rhs < *__lhs); }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Tp>())>
|
||||
{ return !__lhs || *__lhs <= __rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
|
||||
{ return __rhs && !(*__rhs < __lhs); }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Tp>())>
|
||||
{ return __rhs && __lhs <= *__rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
|
||||
{ return __lhs && !(*__lhs < __rhs); }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Tp>())>
|
||||
{ return __lhs && *__lhs >= __rhs; }
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool
|
||||
constexpr auto
|
||||
operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
|
||||
{ return !__rhs || !(__lhs < *__rhs); }
|
||||
-> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Tp>())>
|
||||
{ return !__rhs || __lhs >= *__rhs; }
|
||||
|
||||
// [X.Y.11]
|
||||
template<typename _Tp>
|
||||
|
|
|
@ -54,6 +54,18 @@ namespace ns
|
|||
operator<(value_type const& lhs, value_type const& rhs)
|
||||
{ return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
|
||||
|
||||
constexpr bool
|
||||
operator>(value_type const& lhs, value_type const& rhs)
|
||||
{ return rhs < lhs; }
|
||||
|
||||
constexpr bool
|
||||
operator<=(value_type const& lhs, value_type const& rhs)
|
||||
{ return lhs < rhs || lhs == rhs; }
|
||||
|
||||
constexpr bool
|
||||
operator>=(value_type const& lhs, value_type const& rhs)
|
||||
{ return lhs > rhs || lhs == rhs; }
|
||||
|
||||
} // namespace ns
|
||||
|
||||
int main()
|
||||
|
|
|
@ -54,6 +54,18 @@ namespace ns
|
|||
operator<(value_type const& lhs, value_type const& rhs)
|
||||
{ return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
|
||||
|
||||
constexpr bool
|
||||
operator>(value_type const& lhs, value_type const& rhs)
|
||||
{ return rhs < lhs; }
|
||||
|
||||
constexpr bool
|
||||
operator<=(value_type const& lhs, value_type const& rhs)
|
||||
{ return lhs < rhs || lhs == rhs; }
|
||||
|
||||
constexpr bool
|
||||
operator>=(value_type const& lhs, value_type const& rhs)
|
||||
{ return lhs > rhs || lhs == rhs; }
|
||||
|
||||
} // namespace ns
|
||||
|
||||
int main()
|
||||
|
|
|
@ -36,10 +36,26 @@ namespace ns
|
|||
operator==(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator!=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) != std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator<(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator>(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) > std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator<=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) <= std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator>=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) >= std::tie(rhs.i, rhs.s); }
|
||||
|
||||
} // namespace ns
|
||||
|
||||
int main()
|
||||
|
|
|
@ -36,10 +36,26 @@ namespace ns
|
|||
operator==(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator!=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) != std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator<(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator>(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) > std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator<=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) <= std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator>=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) >= std::tie(rhs.i, rhs.s); }
|
||||
|
||||
} // namespace ns
|
||||
|
||||
int main()
|
||||
|
|
|
@ -36,10 +36,26 @@ namespace ns
|
|||
operator==(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator!=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) != std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator<(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator>(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) > std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator<=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) <= std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator>=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) >= std::tie(rhs.i, rhs.s); }
|
||||
|
||||
} // namespace ns
|
||||
|
||||
int main()
|
||||
|
|
|
@ -36,10 +36,26 @@ namespace ns
|
|||
operator==(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator!=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) != std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator<(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator>(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) > std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator<=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) <= std::tie(rhs.i, rhs.s); }
|
||||
|
||||
bool
|
||||
operator>=(value_type const& lhs, value_type const& rhs)
|
||||
{ return std::tie(lhs.i, lhs.s) >= std::tie(rhs.i, rhs.s); }
|
||||
|
||||
} // namespace ns
|
||||
|
||||
int main()
|
||||
|
|
|
@ -257,3 +257,82 @@ int main()
|
|||
static_assert( *o == 33, "" );
|
||||
}
|
||||
}
|
||||
|
||||
using std::void_t;
|
||||
using std::declval;
|
||||
using std::true_type;
|
||||
using std::false_type;
|
||||
|
||||
template <class T, class = void>
|
||||
struct is_eq_comparable : false_type {};
|
||||
template <class T>
|
||||
struct is_eq_comparable<T, void_t<decltype(declval<T>() == declval<T>())>>
|
||||
: true_type {};
|
||||
|
||||
template <class T, class = void>
|
||||
struct is_neq_comparable : false_type {};
|
||||
template <class T>
|
||||
struct is_neq_comparable<T, void_t<decltype(declval<T>() != declval<T>())>>
|
||||
: true_type {};
|
||||
|
||||
template <class T, class = void>
|
||||
struct is_lt_comparable : false_type {};
|
||||
template <class T>
|
||||
struct is_lt_comparable<T, void_t<decltype(declval<T>() < declval<T>())>>
|
||||
: true_type {};
|
||||
|
||||
template <class T, class = void>
|
||||
struct is_gt_comparable : false_type {};
|
||||
template <class T>
|
||||
struct is_gt_comparable<T, void_t<decltype(declval<T>() > declval<T>())>>
|
||||
: true_type {};
|
||||
|
||||
template <class T, class = void>
|
||||
struct is_le_comparable : false_type {};
|
||||
template <class T>
|
||||
struct is_le_comparable<T, void_t<decltype(declval<T>() <= declval<T>())>>
|
||||
: true_type {};
|
||||
|
||||
template <class T, class = void>
|
||||
struct is_ge_comparable : false_type {};
|
||||
template <class T>
|
||||
struct is_ge_comparable<T, void_t<decltype(declval<T>() >= declval<T>())>>
|
||||
: true_type {};
|
||||
|
||||
using std::optional;
|
||||
|
||||
static_assert(is_eq_comparable<optional<int>>::value, "");
|
||||
static_assert(is_neq_comparable<optional<int>>::value, "");
|
||||
static_assert(is_lt_comparable<optional<int>>::value, "");
|
||||
static_assert(is_gt_comparable<optional<int>>::value, "");
|
||||
static_assert(is_le_comparable<optional<int>>::value, "");
|
||||
static_assert(is_ge_comparable<optional<int>>::value, "");
|
||||
|
||||
struct JustEq {};
|
||||
bool operator==(const JustEq&, const JustEq&);
|
||||
|
||||
static_assert(is_eq_comparable<optional<JustEq>>::value, "");
|
||||
static_assert(!is_neq_comparable<optional<JustEq>>::value, "");
|
||||
static_assert(!is_lt_comparable<optional<JustEq>>::value, "");
|
||||
static_assert(!is_gt_comparable<optional<JustEq>>::value, "");
|
||||
static_assert(!is_le_comparable<optional<JustEq>>::value, "");
|
||||
static_assert(!is_ge_comparable<optional<JustEq>>::value, "");
|
||||
|
||||
struct JustLt {};
|
||||
bool operator<(const JustLt&, const JustLt&);
|
||||
|
||||
static_assert(!is_eq_comparable<optional<JustLt>>::value, "");
|
||||
static_assert(!is_neq_comparable<optional<JustLt>>::value, "");
|
||||
static_assert(is_lt_comparable<optional<JustLt>>::value, "");
|
||||
static_assert(!is_gt_comparable<optional<JustLt>>::value, "");
|
||||
static_assert(!is_le_comparable<optional<JustLt>>::value, "");
|
||||
static_assert(!is_ge_comparable<optional<JustLt>>::value, "");
|
||||
|
||||
static_assert(!std::is_assignable<optional<JustEq>&,
|
||||
optional<JustLt>>::value, "");
|
||||
static_assert(!std::is_assignable<optional<JustEq>&,
|
||||
JustLt>::value, "");
|
||||
static_assert(!std::is_assignable<optional<JustEq>&,
|
||||
optional<JustLt>&>::value, "");
|
||||
static_assert(!std::is_assignable<optional<JustEq>&,
|
||||
JustLt&>::value, "");
|
||||
|
|
Loading…
Reference in New Issue