• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef TRANSPARENT_H
10 #define TRANSPARENT_H
11 
12 #include "test_macros.h"
13 
14 #include <functional> // for std::equal_to
15 
16 // testing transparent
17 #if TEST_STD_VER > 11
18 
19 struct transparent_less
20 {
21     template <class T, class U>
22     constexpr auto operator()(T&& t, U&& u) const
23     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
24     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
25         { return      std::forward<T>(t) < std::forward<U>(u); }
26     using is_transparent = void;  // correct
27 };
28 
29 struct transparent_less_not_referenceable
30 {
31     template <class T, class U>
32     constexpr auto operator()(T&& t, U&& u) const
33     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
34     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
35         { return      std::forward<T>(t) < std::forward<U>(u); }
36     using is_transparent = void () const &;  // it's a type; a weird one, but a type
37 };
38 
39 struct transparent_less_no_type
40 {
41     template <class T, class U>
42     constexpr auto operator()(T&& t, U&& u) const
43     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
44     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
45         { return      std::forward<T>(t) < std::forward<U>(u); }
46 private:
47 //    using is_transparent = void;  // error - should exist
48 };
49 
50 struct transparent_less_private
51 {
52     template <class T, class U>
53     constexpr auto operator()(T&& t, U&& u) const
54     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
55     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
56         { return      std::forward<T>(t) < std::forward<U>(u); }
57 private:
58     using is_transparent = void;  // error - should be accessible
59 };
60 
61 struct transparent_less_not_a_type
62 {
63     template <class T, class U>
64     constexpr auto operator()(T&& t, U&& u) const
65     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
66     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
67         { return      std::forward<T>(t) < std::forward<U>(u); }
68 
69     int is_transparent;  // error - should be a type
70 };
71 
72 struct C2Int { // comparable to int
C2IntC2Int73     C2Int() : i_(0) {}
C2IntC2Int74     C2Int(int i): i_(i) {}
getC2Int75     int get () const { return i_; }
76 private:
77     int i_;
78     };
79 
80 bool operator <(int          rhs,   const C2Int& lhs) { return rhs       < lhs.get(); }
81 bool operator <(const C2Int& rhs,   const C2Int& lhs) { return rhs.get() < lhs.get(); }
82 bool operator <(const C2Int& rhs,            int lhs) { return rhs.get() < lhs; }
83 
84 #endif // TEST_STD_VER > 11
85 
86 #if TEST_STD_VER > 17
87 
88 template <typename T>
89 struct StoredType;
90 
91 template <typename T>
92 struct SearchedType;
93 
94 struct hash_impl {
95   template <typename T>
operatorhash_impl96   constexpr std::size_t operator()(SearchedType<T> const& t) const {
97     return static_cast<std::size_t>(t.get_value());
98   }
99 
100   template <typename T>
operatorhash_impl101   constexpr std::size_t operator()(StoredType<T> const& t) const {
102     return static_cast<std::size_t>(t.get_value());
103   }
104 };
105 
106 struct non_transparent_hash : hash_impl {};
107 
108 struct transparent_hash : hash_impl {
109   using is_transparent = void;
110 };
111 
112 struct transparent_hash_final final : transparent_hash {};
113 
114 struct transparent_equal_final final : std::equal_to<> {};
115 
116 template <typename T>
117 struct SearchedType {
SearchedTypeSearchedType118   SearchedType(T value, int* counter) : value_(value), conversions_(counter) { }
119 
120   // Whenever a conversion is performed, increment the counter to keep track
121   // of conversions.
122   operator StoredType<T>() const {
123     ++*conversions_;
124     return StoredType<T>{value_};
125   }
126 
get_valueSearchedType127   int get_value() const {
128     return value_;
129   }
130 
131 private:
132   T value_;
133   int* conversions_;
134 };
135 
136 template <typename T>
137 struct StoredType {
138   StoredType() = default;
StoredTypeStoredType139   StoredType(T value) : value_(value) { }
140 
141   friend bool operator==(StoredType const& lhs, StoredType const& rhs) {
142     return lhs.value_ == rhs.value_;
143   }
144 
145   // If we're being passed a SearchedType<T> object, avoid the conversion
146   // to T. This allows testing that the transparent operations are correctly
147   // forwarding the SearchedType all the way to this comparison by checking
148   // that we didn't have a conversion when we search for a SearchedType<T>
149   // in a container full of StoredType<T>.
150   friend bool operator==(StoredType const& lhs, SearchedType<T> const& rhs) {
151     return lhs.value_ == rhs.get_value();
152   }
153   friend bool operator==(SearchedType<T> const& lhs, StoredType<T> const& rhs) {
154     return lhs.get_value() == rhs.value_;
155   }
156 
get_valueStoredType157   int get_value() const {
158     return value_;
159   }
160 
161 private:
162   T value_;
163 };
164 
165 #endif // TEST_STD_VER > 17
166 
167 #endif  // TRANSPARENT_H
168