mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-15 19:01:09 +08:00
PR libstdc++/78420 Make std::less etc. yield total order for pointers
In order for std::less<T*> etc. to meet the total order requirements of [comparisons] p2 we need to cast unrelated pointers to uintptr_t before comparing them. Those casts aren't allowed in constant expressions, so only cast when __builtin_constant_p says the result of the comparison is not a compile-time constant (because the arguments are not constants, or the result of the comparison is unspecified). When the result is constant just compare the pointers directly without casting. This ensures that the function can be called in constant expressions with suitable arguments, but still yields a total order even for otherwise unspecified pointer comparisons. For std::less<void> etc. add new overloads for pointers, which use std::less<common_type_t<T*,U*>> directly. Also change the generic overloads to detect when the comparison would call a built-in relational operator with pointer operands, and dispatch that case to the corresponding specialization for void pointers. PR libstdc++/78420 * include/bits/stl_function.h (greater<_Tp*>, less<_Tp*>) (greater_equal<_Tp*>, less_equal<_Tp>*): Add partial specializations to ensure total order for pointers. (greater<void>, less<void>, greater_equal<void>, less_equal<void>): Add operator() overloads for pointer arguments and make generic overloads dispatch to new _S_cmp functions when comparisons would use built-in operators for pointers. * testsuite/20_util/function_objects/comparisons_pointer.cc: New. From-SVN: r258540
This commit is contained in:
parent
dcdfd47859
commit
0b3ec8f48f
libstdc++-v3
@ -1,3 +1,15 @@
|
||||
2018-03-14 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/78420
|
||||
* include/bits/stl_function.h (greater<_Tp*>, less<_Tp*>)
|
||||
(greater_equal<_Tp*>, less_equal<_Tp>*): Add partial specializations
|
||||
to ensure total order for pointers.
|
||||
(greater<void>, less<void>, greater_equal<void>, less_equal<void>):
|
||||
Add operator() overloads for pointer arguments and make generic
|
||||
overloads dispatch to new _S_cmp functions when comparisons would
|
||||
use built-in operators for pointers.
|
||||
* testsuite/20_util/function_objects/comparisons_pointer.cc: New.
|
||||
|
||||
2018-03-12 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/84773
|
||||
|
@ -406,14 +406,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{ return __x <= __y; }
|
||||
};
|
||||
|
||||
#if __cplusplus > 201103L
|
||||
// Partial specialization of std::greater for pointers.
|
||||
template<typename _Tp>
|
||||
struct greater<_Tp*> : public binary_function<_Tp*, _Tp*, bool>
|
||||
{
|
||||
_GLIBCXX14_CONSTEXPR bool
|
||||
operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW
|
||||
{
|
||||
if (__builtin_constant_p (__x > __y))
|
||||
return __x > __y;
|
||||
return (__UINTPTR_TYPE__)__x > (__UINTPTR_TYPE__)__y;
|
||||
}
|
||||
};
|
||||
|
||||
// Partial specialization of std::less for pointers.
|
||||
template<typename _Tp>
|
||||
struct less<_Tp*> : public binary_function<_Tp*, _Tp*, bool>
|
||||
{
|
||||
_GLIBCXX14_CONSTEXPR bool
|
||||
operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW
|
||||
{
|
||||
if (__builtin_constant_p (__x < __y))
|
||||
return __x < __y;
|
||||
return (__UINTPTR_TYPE__)__x < (__UINTPTR_TYPE__)__y;
|
||||
}
|
||||
};
|
||||
|
||||
// Partial specialization of std::greater_equal for pointers.
|
||||
template<typename _Tp>
|
||||
struct greater_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool>
|
||||
{
|
||||
_GLIBCXX14_CONSTEXPR bool
|
||||
operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW
|
||||
{
|
||||
if (__builtin_constant_p (__x >= __y))
|
||||
return __x >= __y;
|
||||
return (__UINTPTR_TYPE__)__x >= (__UINTPTR_TYPE__)__y;
|
||||
}
|
||||
};
|
||||
|
||||
// Partial specialization of std::less_equal for pointers.
|
||||
template<typename _Tp>
|
||||
struct less_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool>
|
||||
{
|
||||
_GLIBCXX14_CONSTEXPR bool
|
||||
operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW
|
||||
{
|
||||
if (__builtin_constant_p (__x <= __y))
|
||||
return __x <= __y;
|
||||
return (__UINTPTR_TYPE__)__x <= (__UINTPTR_TYPE__)__y;
|
||||
}
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
/// One of the @link comparison_functors comparison functors@endlink.
|
||||
template<>
|
||||
struct equal_to<void>
|
||||
{
|
||||
template <typename _Tp, typename _Up>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
auto
|
||||
constexpr auto
|
||||
operator()(_Tp&& __t, _Up&& __u) const
|
||||
noexcept(noexcept(std::forward<_Tp>(__t) == std::forward<_Up>(__u)))
|
||||
-> decltype(std::forward<_Tp>(__t) == std::forward<_Up>(__u))
|
||||
@ -427,8 +478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
struct not_equal_to<void>
|
||||
{
|
||||
template <typename _Tp, typename _Up>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
auto
|
||||
constexpr auto
|
||||
operator()(_Tp&& __t, _Up&& __u) const
|
||||
noexcept(noexcept(std::forward<_Tp>(__t) != std::forward<_Up>(__u)))
|
||||
-> decltype(std::forward<_Tp>(__t) != std::forward<_Up>(__u))
|
||||
@ -442,14 +492,62 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
struct greater<void>
|
||||
{
|
||||
template <typename _Tp, typename _Up>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
auto
|
||||
constexpr auto
|
||||
operator()(_Tp&& __t, _Up&& __u) const
|
||||
noexcept(noexcept(std::forward<_Tp>(__t) > std::forward<_Up>(__u)))
|
||||
-> decltype(std::forward<_Tp>(__t) > std::forward<_Up>(__u))
|
||||
{ return std::forward<_Tp>(__t) > std::forward<_Up>(__u); }
|
||||
{
|
||||
return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u),
|
||||
__ptr_cmp<_Tp, _Up>{});
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
constexpr bool
|
||||
operator()(_Tp* __t, _Up* __u) const noexcept
|
||||
{ return greater<common_type_t<_Tp*, _Up*>>{}(__t, __u); }
|
||||
|
||||
typedef __is_transparent is_transparent;
|
||||
|
||||
private:
|
||||
template <typename _Tp, typename _Up>
|
||||
static constexpr decltype(auto)
|
||||
_S_cmp(_Tp&& __t, _Up&& __u, false_type)
|
||||
{ return std::forward<_Tp>(__t) > std::forward<_Up>(__u); }
|
||||
|
||||
template <typename _Tp, typename _Up>
|
||||
static constexpr bool
|
||||
_S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept
|
||||
{
|
||||
return greater<const volatile void*>{}(
|
||||
static_cast<const volatile void*>(std::forward<_Tp>(__t)),
|
||||
static_cast<const volatile void*>(std::forward<_Up>(__u)));
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __not_overloaded;
|
||||
|
||||
// False if we can call operator>(T,U)
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded<_Tp, _Up, __void_t<
|
||||
decltype(operator>(std::declval<_Tp>(), std::declval<_Up>()))>>
|
||||
: false_type { };
|
||||
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __not_overloaded2 : true_type { };
|
||||
|
||||
// False if we can call T.operator>(U)
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded2<_Tp, _Up, __void_t<
|
||||
decltype(std::declval<_Tp>().operator>(std::declval<_Up>()))>>
|
||||
: false_type { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded<_Tp, _Up> : __not_overloaded2<_Tp, _Up> { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>,
|
||||
is_convertible<_Tp, const volatile void*>,
|
||||
is_convertible<_Up, const volatile void*>>;
|
||||
};
|
||||
|
||||
/// One of the @link comparison_functors comparison functors@endlink.
|
||||
@ -457,14 +555,62 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
struct less<void>
|
||||
{
|
||||
template <typename _Tp, typename _Up>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
auto
|
||||
constexpr auto
|
||||
operator()(_Tp&& __t, _Up&& __u) const
|
||||
noexcept(noexcept(std::forward<_Tp>(__t) < std::forward<_Up>(__u)))
|
||||
-> decltype(std::forward<_Tp>(__t) < std::forward<_Up>(__u))
|
||||
{ return std::forward<_Tp>(__t) < std::forward<_Up>(__u); }
|
||||
{
|
||||
return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u),
|
||||
__ptr_cmp<_Tp, _Up>{});
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
constexpr bool
|
||||
operator()(_Tp* __t, _Up* __u) const noexcept
|
||||
{ return less<common_type_t<_Tp*, _Up*>>{}(__t, __u); }
|
||||
|
||||
typedef __is_transparent is_transparent;
|
||||
|
||||
private:
|
||||
template <typename _Tp, typename _Up>
|
||||
static constexpr decltype(auto)
|
||||
_S_cmp(_Tp&& __t, _Up&& __u, false_type)
|
||||
{ return std::forward<_Tp>(__t) < std::forward<_Up>(__u); }
|
||||
|
||||
template <typename _Tp, typename _Up>
|
||||
static constexpr bool
|
||||
_S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept
|
||||
{
|
||||
return less<const volatile void*>{}(
|
||||
static_cast<const volatile void*>(std::forward<_Tp>(__t)),
|
||||
static_cast<const volatile void*>(std::forward<_Up>(__u)));
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __not_overloaded;
|
||||
|
||||
// False if we can call operator<(T,U)
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded<_Tp, _Up, __void_t<
|
||||
decltype(operator<(std::declval<_Tp>(), std::declval<_Up>()))>>
|
||||
: false_type { };
|
||||
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __not_overloaded2 : true_type { };
|
||||
|
||||
// False if we can call T.operator<(U)
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded2<_Tp, _Up, __void_t<
|
||||
decltype(std::declval<_Tp>().operator<(std::declval<_Up>()))>>
|
||||
: false_type { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded<_Tp, _Up> : __not_overloaded2<_Tp, _Up> { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>,
|
||||
is_convertible<_Tp, const volatile void*>,
|
||||
is_convertible<_Up, const volatile void*>>;
|
||||
};
|
||||
|
||||
/// One of the @link comparison_functors comparison functors@endlink.
|
||||
@ -472,14 +618,62 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
struct greater_equal<void>
|
||||
{
|
||||
template <typename _Tp, typename _Up>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
auto
|
||||
constexpr auto
|
||||
operator()(_Tp&& __t, _Up&& __u) const
|
||||
noexcept(noexcept(std::forward<_Tp>(__t) >= std::forward<_Up>(__u)))
|
||||
-> decltype(std::forward<_Tp>(__t) >= std::forward<_Up>(__u))
|
||||
{ return std::forward<_Tp>(__t) >= std::forward<_Up>(__u); }
|
||||
{
|
||||
return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u),
|
||||
__ptr_cmp<_Tp, _Up>{});
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
constexpr bool
|
||||
operator()(_Tp* __t, _Up* __u) const noexcept
|
||||
{ return greater_equal<common_type_t<_Tp*, _Up*>>{}(__t, __u); }
|
||||
|
||||
typedef __is_transparent is_transparent;
|
||||
|
||||
private:
|
||||
template <typename _Tp, typename _Up>
|
||||
static constexpr decltype(auto)
|
||||
_S_cmp(_Tp&& __t, _Up&& __u, false_type)
|
||||
{ return std::forward<_Tp>(__t) >= std::forward<_Up>(__u); }
|
||||
|
||||
template <typename _Tp, typename _Up>
|
||||
static constexpr bool
|
||||
_S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept
|
||||
{
|
||||
return greater_equal<const volatile void*>{}(
|
||||
static_cast<const volatile void*>(std::forward<_Tp>(__t)),
|
||||
static_cast<const volatile void*>(std::forward<_Up>(__u)));
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __not_overloaded;
|
||||
|
||||
// False if we can call operator>=(T,U)
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded<_Tp, _Up, __void_t<
|
||||
decltype(operator>=(std::declval<_Tp>(), std::declval<_Up>()))>>
|
||||
: false_type { };
|
||||
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __not_overloaded2 : true_type { };
|
||||
|
||||
// False if we can call T.operator>=(U)
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded2<_Tp, _Up, __void_t<
|
||||
decltype(std::declval<_Tp>().operator>=(std::declval<_Up>()))>>
|
||||
: false_type { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded<_Tp, _Up> : __not_overloaded2<_Tp, _Up> { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>,
|
||||
is_convertible<_Tp, const volatile void*>,
|
||||
is_convertible<_Up, const volatile void*>>;
|
||||
};
|
||||
|
||||
/// One of the @link comparison_functors comparison functors@endlink.
|
||||
@ -487,16 +681,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
struct less_equal<void>
|
||||
{
|
||||
template <typename _Tp, typename _Up>
|
||||
_GLIBCXX14_CONSTEXPR
|
||||
auto
|
||||
constexpr auto
|
||||
operator()(_Tp&& __t, _Up&& __u) const
|
||||
noexcept(noexcept(std::forward<_Tp>(__t) <= std::forward<_Up>(__u)))
|
||||
-> decltype(std::forward<_Tp>(__t) <= std::forward<_Up>(__u))
|
||||
{ return std::forward<_Tp>(__t) <= std::forward<_Up>(__u); }
|
||||
{
|
||||
return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u),
|
||||
__ptr_cmp<_Tp, _Up>{});
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
constexpr bool
|
||||
operator()(_Tp* __t, _Up* __u) const noexcept
|
||||
{ return less_equal<common_type_t<_Tp*, _Up*>>{}(__t, __u); }
|
||||
|
||||
typedef __is_transparent is_transparent;
|
||||
|
||||
private:
|
||||
template <typename _Tp, typename _Up>
|
||||
static constexpr decltype(auto)
|
||||
_S_cmp(_Tp&& __t, _Up&& __u, false_type)
|
||||
{ return std::forward<_Tp>(__t) <= std::forward<_Up>(__u); }
|
||||
|
||||
template <typename _Tp, typename _Up>
|
||||
static constexpr bool
|
||||
_S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept
|
||||
{
|
||||
return less_equal<const volatile void*>{}(
|
||||
static_cast<const volatile void*>(std::forward<_Tp>(__t)),
|
||||
static_cast<const volatile void*>(std::forward<_Up>(__u)));
|
||||
}
|
||||
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __not_overloaded;
|
||||
|
||||
// False if we can call operator<=(T,U)
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded<_Tp, _Up, __void_t<
|
||||
decltype(operator<=(std::declval<_Tp>(), std::declval<_Up>()))>>
|
||||
: false_type { };
|
||||
|
||||
template<typename _Tp, typename _Up, typename = void>
|
||||
struct __not_overloaded2 : true_type { };
|
||||
|
||||
// False if we can call T.operator<=(U)
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded2<_Tp, _Up, __void_t<
|
||||
decltype(std::declval<_Tp>().operator<=(std::declval<_Up>()))>>
|
||||
: false_type { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __not_overloaded<_Tp, _Up> : __not_overloaded2<_Tp, _Up> { };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>,
|
||||
is_convertible<_Tp, const volatile void*>,
|
||||
is_convertible<_Up, const volatile void*>>;
|
||||
};
|
||||
#endif
|
||||
#endif // C++14
|
||||
/** @} */
|
||||
|
||||
// 20.3.4 logical operations
|
||||
|
@ -0,0 +1,206 @@
|
||||
// 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/>.
|
||||
|
||||
// { dg-do run }
|
||||
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
int b[8];
|
||||
int a[8];
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
auto p = a + 8;
|
||||
std::greater<int*> gt;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << gt(p, b) << ' ' << gt(b, p) << ' ' << (!gt(p, b) && !gt(b, p));
|
||||
int sum = 0, n = 0;
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
VERIFY( sum == 1 );
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
static_assert( gt(a+1, a), "constexpr greater<int*>" );
|
||||
static_assert( !gt(a, a+1), "constexpr greater<int*>" );
|
||||
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
sum = 0;
|
||||
auto p2 = a + 8;
|
||||
std::greater<> gt2;
|
||||
ss << gt2(p2, b) << ' ' << gt2(b, p2) << ' ' << (!gt2(p2, b) && !gt2(b, p2));
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
VERIFY( sum == 1 );
|
||||
|
||||
static_assert( gt2(a+1, a), "constexpr greater<>" );
|
||||
static_assert( !gt2(a, a+1), "constexpr greater<>" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
auto p = a + 8;
|
||||
std::less<int*> lt;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << lt(p, b) << ' ' << lt(b, p) << ' ' << (!lt(p, b) && !lt(b, p));
|
||||
int sum = 0, n = 0;
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
VERIFY( sum == 1 );
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
static_assert( lt(a, a+1), "constexpr less<int*>" );
|
||||
static_assert( !lt(a+1, a), "constexpr less<int*>" );
|
||||
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
sum = 0;
|
||||
auto p2 = a + 8;
|
||||
std::less<> lt2;
|
||||
ss << lt2(p2, b) << ' ' << lt2(b, p2) << ' ' << (!lt2(p2, b) && !lt2(b, p2));
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
VERIFY( sum == 1 );
|
||||
|
||||
static_assert( lt2(a, a+1), "constexpr less<>" );
|
||||
static_assert( !lt2(a+1, a), "constexpr less<>" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
auto p = a + 8;
|
||||
std::greater_equal<int*> ge;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << !ge(p, b) << ' ' << !ge(b, p) << ' ' << (ge(p, b) && ge(b, p));
|
||||
int sum = 0, n = 0;
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
VERIFY( sum == 1 );
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
static_assert( !ge(a, a+1), "constexpr greater_equal<int*>" );
|
||||
static_assert( ge(a, a), "constexpr greater_equal<int*>" );
|
||||
static_assert( ge(a+1, a), "constexpr greater_equal<int*>" );
|
||||
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
sum = 0;
|
||||
auto p2 = a + 8;
|
||||
std::greater_equal<> ge2;
|
||||
ss << !ge2(p2, b) << ' ' << !ge2(b, p2) << ' ' << (ge2(p2, b) && ge2(b, p2));
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
VERIFY( sum == 1 );
|
||||
|
||||
static_assert( !ge2(a, a+1), "constexpr greater_equal<>" );
|
||||
static_assert( ge2(a, a), "constexpr greater_equal<>" );
|
||||
static_assert( ge2(a+1, a), "constexpr greater_equal<>" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
test04()
|
||||
{
|
||||
auto p = a + 8;
|
||||
std::less_equal<int*> le;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << !le(p, b) << ' ' << !le(b, p) << ' ' << (le(p, b) && le(b, p));
|
||||
int sum = 0, n = 0;
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
VERIFY( sum == 1 );
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
static_assert( !le(a+1, a), "constexpr less_equal<int*>" );
|
||||
static_assert( le(a, a), "constexpr less_equal<int*>" );
|
||||
static_assert( le(a, a+1), "constexpr less_equal<int*>" );
|
||||
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
sum = 0;
|
||||
auto p2 = a + 8;
|
||||
std::less_equal<> le2;
|
||||
ss << !le2(p2, b) << ' ' << !le2(b, p2) << ' ' << (le2(p2, b) && le2(b, p2));
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
VERIFY( sum == 1 );
|
||||
|
||||
static_assert( !le2(a+1, a), "constexpr less_equal<>" );
|
||||
static_assert( le2(a, a), "constexpr less_equal<>" );
|
||||
static_assert( le2(a, a+1), "constexpr less_equal<>" );
|
||||
#endif
|
||||
}
|
||||
|
||||
struct X {
|
||||
operator const X*() const { return this; }
|
||||
};
|
||||
|
||||
X x;
|
||||
X y[4];
|
||||
|
||||
void
|
||||
test05()
|
||||
{
|
||||
std::less<const X*> lt;
|
||||
auto p = y + 4;
|
||||
std::stringstream ss;
|
||||
ss << lt(x, p) << ' ' << lt(p, x) << ' ' << (!lt(p, x) && !lt(x, p));
|
||||
int sum = 0;
|
||||
int n = 0;
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
assert( sum == 1 );
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
static_assert( lt(y, y+1), "constexpr less<const X*>" );
|
||||
static_assert( !lt(y+1, y), "constexpr less<const X*>" );
|
||||
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
sum = 0;
|
||||
auto p2 = y + 4;
|
||||
std::less<> lt2;
|
||||
ss << lt2(x, p2) << ' ' << lt2(p2, x) << ' ' << (!lt2(x, p2) && !lt2(p2, x));
|
||||
while (ss >> n)
|
||||
sum += n;
|
||||
VERIFY( sum == 1 );
|
||||
|
||||
static_assert( lt2(y, y+1), "constexpr less<>" );
|
||||
static_assert( !lt2(y+1, y), "constexpr less<>" );
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
test04();
|
||||
test05();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user