summaryrefslogtreecommitdiffstats
path: root/clang/test/CXX/class/class.compare/class.spaceship/p2.cpp
blob: a912384ccf7693ee713f6214219030a20f96743d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// RUN: %clang_cc1 -std=c++2a -verify %s

namespace std {
  class strong_ordering {
    int n;
    constexpr strong_ordering(int n) : n(n) {}
  public:
    static const strong_ordering less, equal, greater;
    bool operator!=(int) { return n != 0; }
  };
  constexpr strong_ordering strong_ordering::less{-1},
      strong_ordering::equal{0}, strong_ordering::greater{1};

  class weak_ordering {
    int n;
    constexpr weak_ordering(int n) : n(n) {}
  public:
    constexpr weak_ordering(strong_ordering o);
    static const weak_ordering less, equivalent, greater;
    bool operator!=(int) { return n != 0; }
  };
  constexpr weak_ordering weak_ordering::less{-1},
      weak_ordering::equivalent{0}, weak_ordering::greater{1};

  class partial_ordering {
    int n;
    constexpr partial_ordering(int n) : n(n) {}
  public:
    constexpr partial_ordering(strong_ordering o);
    constexpr partial_ordering(weak_ordering o);
    static const partial_ordering less, equivalent, greater, unordered;
    bool operator!=(int) { return n != 0; }
  };
  constexpr partial_ordering partial_ordering::less{-1},
      partial_ordering::equivalent{0}, partial_ordering::greater{1},
      partial_ordering::unordered{2};
}

namespace DeducedNotCat {
  struct A {
    A operator<=>(const A&) const; // expected-note {{selected 'operator<=>' for member 'a' declared here}}
  };
  struct B {
    A a; // expected-note {{return type 'DeducedNotCat::A' of three-way comparison for member 'a' is not a standard comparison category type}}
    auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}}
  };
}

namespace DeducedVsSynthesized {
  struct A {
    bool operator==(const A&) const;
    bool operator<(const A&) const;
  };
  struct B {
    A a; // expected-note {{no viable comparison function for member 'a'}}
    auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}}
  };
}

namespace Deduction {
  template<typename T> struct wrap {
    T t;
    friend auto operator<=>(const wrap&, const wrap&) = default;
  };

  using strong = wrap<int>;
  using strong2 = wrap<int*>;
  struct weak {
    friend std::weak_ordering operator<=>(weak, weak);
  };
  using partial = wrap<float>;

  template<typename ...T> struct A : T... {
    friend auto operator<=>(const A&, const A&) = default;
  };

  template<typename Expected, typename ...Ts> void f() {
    using T = Expected; // expected-note {{previous}}
    using T = decltype(A<Ts...>() <=> A<Ts...>()); // expected-error {{different type}}
    void(A<Ts...>() <=> A<Ts...>()); // trigger synthesis of body
  }

  template void f<std::strong_ordering>();
  template void f<std::strong_ordering, strong>();
  template void f<std::strong_ordering, strong, strong2>();

  template void f<std::weak_ordering, weak>();
  template void f<std::weak_ordering, weak, strong>();
  template void f<std::weak_ordering, strong, weak>();

  template void f<std::partial_ordering, partial>();
  template void f<std::partial_ordering, weak, partial>();
  template void f<std::partial_ordering, strong, partial>();
  template void f<std::partial_ordering, partial, weak>();
  template void f<std::partial_ordering, partial, strong>();
  template void f<std::partial_ordering, weak, partial, strong>();

  // Check that the above mechanism works.
  template void f<std::strong_ordering, weak>(); // expected-note {{instantiation of}}
}

namespace BadDeducedType {
  struct A {
    // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'auto &'}}
    friend auto &operator<=>(const A&, const A&) = default;
  };

  struct B {
    // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'const auto'}}
    friend const auto operator<=>(const B&, const B&) = default;
  };

  template<typename T> struct X {}; // expected-note {{here}}
  struct C {
    // expected-error@+1 {{deduction not allowed in function return type}}
    friend X operator<=>(const C&, const C&) = default;
  };

  template<typename T> concept CmpCat = true;
  struct D {
    // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'CmpCat auto'}}
    friend CmpCat auto operator<=>(const D&, const D&) = default;
  };
}
OpenPOWER on IntegriCloud