| // This is a test for a hack in Clang that works around a problem introduced by |
| // DR583: it's no longer possible to compare a pointer against nullptr_t, but |
| // we still want to permit those comparisons within less<> and friends. |
| |
| // RUN: %clang_cc1 -verify %s -std=c++14 |
| |
| namespace std { |
| template<typename T = void> struct less {}; |
| template<typename T = void> struct less_equal {}; |
| template<typename T = void> struct greater {}; |
| template<typename T = void> struct greater_equal {}; |
| |
| template<> struct less<> { |
| template <class T1, class T2> |
| auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u)) |
| -> decltype(t < u) { |
| return t < u; |
| } |
| }; |
| |
| template<> struct less_equal<> { |
| template <class T1, class T2> |
| auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t <= u)) |
| -> decltype(t <= u) { |
| return t <= u; |
| } |
| }; |
| |
| template<> struct greater<> { |
| template <class T1, class T2> |
| auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t > u)) |
| -> decltype(t > u) { |
| return t > u; |
| } |
| }; |
| |
| template<> struct greater_equal<> { |
| template <class T1, class T2> |
| auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t >= u)) |
| -> decltype(t >= u) { |
| return t >= u; |
| } |
| }; |
| |
| template<typename = void> struct unrelated; |
| template<> struct unrelated<> { |
| template <class T1, class T2> |
| auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u)) // expected-note {{substitution failure}} |
| -> decltype(t < u) { |
| return t < u; |
| } |
| }; |
| }; |
| |
| void test(int *p) { |
| using namespace std; |
| less<>()(p, nullptr); |
| less<>()(nullptr, p); |
| less_equal<>()(p, nullptr); |
| less_equal<>()(nullptr, p); |
| greater<>()(p, nullptr); |
| greater<>()(nullptr, p); |
| greater_equal<>()(p, nullptr); |
| greater_equal<>()(nullptr, p); |
| |
| unrelated<>()(p, nullptr); // expected-error {{no matching function}} |
| } |