{ 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))
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))
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.
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.
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.
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
--- /dev/null
+// 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();
+}