168 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef TRANSPARENT_H
 | |
| #define TRANSPARENT_H
 | |
| 
 | |
| #include "test_macros.h"
 | |
| 
 | |
| #include <functional> // for std::equal_to
 | |
| 
 | |
| // testing transparent
 | |
| #if TEST_STD_VER > 11
 | |
| 
 | |
| struct transparent_less
 | |
| {
 | |
|     template <class T, class U>
 | |
|     constexpr auto operator()(T&& t, U&& u) const
 | |
|     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
 | |
|     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
 | |
|         { return      std::forward<T>(t) < std::forward<U>(u); }
 | |
|     using is_transparent = void;  // correct
 | |
| };
 | |
| 
 | |
| struct transparent_less_not_referenceable
 | |
| {
 | |
|     template <class T, class U>
 | |
|     constexpr auto operator()(T&& t, U&& u) const
 | |
|     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
 | |
|     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
 | |
|         { return      std::forward<T>(t) < std::forward<U>(u); }
 | |
|     using is_transparent = void () const &;  // it's a type; a weird one, but a type
 | |
| };
 | |
| 
 | |
| struct transparent_less_no_type
 | |
| {
 | |
|     template <class T, class U>
 | |
|     constexpr auto operator()(T&& t, U&& u) const
 | |
|     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
 | |
|     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
 | |
|         { return      std::forward<T>(t) < std::forward<U>(u); }
 | |
| private:
 | |
| //    using is_transparent = void;  // error - should exist
 | |
| };
 | |
| 
 | |
| struct transparent_less_private
 | |
| {
 | |
|     template <class T, class U>
 | |
|     constexpr auto operator()(T&& t, U&& u) const
 | |
|     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
 | |
|     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
 | |
|         { return      std::forward<T>(t) < std::forward<U>(u); }
 | |
| private:
 | |
|     using is_transparent = void;  // error - should be accessible
 | |
| };
 | |
| 
 | |
| struct transparent_less_not_a_type
 | |
| {
 | |
|     template <class T, class U>
 | |
|     constexpr auto operator()(T&& t, U&& u) const
 | |
|     noexcept(noexcept(std::forward<T>(t) < std::forward<U>(u)))
 | |
|     -> decltype      (std::forward<T>(t) < std::forward<U>(u))
 | |
|         { return      std::forward<T>(t) < std::forward<U>(u); }
 | |
| 
 | |
|     int is_transparent;  // error - should be a type
 | |
| };
 | |
| 
 | |
| struct C2Int { // comparable to int
 | |
|     C2Int() : i_(0) {}
 | |
|     C2Int(int i): i_(i) {}
 | |
|     int get () const { return i_; }
 | |
| private:
 | |
|     int i_;
 | |
|     };
 | |
| 
 | |
| bool operator <(int          rhs,   const C2Int& lhs) { return rhs       < lhs.get(); }
 | |
| bool operator <(const C2Int& rhs,   const C2Int& lhs) { return rhs.get() < lhs.get(); }
 | |
| bool operator <(const C2Int& rhs,            int lhs) { return rhs.get() < lhs; }
 | |
| 
 | |
| #endif // TEST_STD_VER > 11
 | |
| 
 | |
| #if TEST_STD_VER > 17
 | |
| 
 | |
| template <typename T>
 | |
| struct StoredType;
 | |
| 
 | |
| template <typename T>
 | |
| struct SearchedType;
 | |
| 
 | |
| struct hash_impl {
 | |
|   template <typename T>
 | |
|   constexpr std::size_t operator()(SearchedType<T> const& t) const {
 | |
|     return static_cast<std::size_t>(t.get_value());
 | |
|   }
 | |
| 
 | |
|   template <typename T>
 | |
|   constexpr std::size_t operator()(StoredType<T> const& t) const {
 | |
|     return static_cast<std::size_t>(t.get_value());
 | |
|   }
 | |
| };
 | |
| 
 | |
| struct non_transparent_hash : hash_impl {};
 | |
| 
 | |
| struct transparent_hash : hash_impl {
 | |
|   using is_transparent = void;
 | |
| };
 | |
| 
 | |
| struct transparent_hash_final final : transparent_hash {};
 | |
| 
 | |
| struct transparent_equal_final final : std::equal_to<> {};
 | |
| 
 | |
| template <typename T>
 | |
| struct SearchedType {
 | |
|   SearchedType(T value, int* counter) : value_(value), conversions_(counter) { }
 | |
| 
 | |
|   // Whenever a conversion is performed, increment the counter to keep track
 | |
|   // of conversions.
 | |
|   operator StoredType<T>() const {
 | |
|     ++*conversions_;
 | |
|     return StoredType<T>{value_};
 | |
|   }
 | |
| 
 | |
|   int get_value() const {
 | |
|     return value_;
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   T value_;
 | |
|   int* conversions_;
 | |
| };
 | |
| 
 | |
| template <typename T>
 | |
| struct StoredType {
 | |
|   StoredType() = default;
 | |
|   StoredType(T value) : value_(value) { }
 | |
| 
 | |
|   friend bool operator==(StoredType const& lhs, StoredType const& rhs) {
 | |
|     return lhs.value_ == rhs.value_;
 | |
|   }
 | |
| 
 | |
|   // If we're being passed a SearchedType<T> object, avoid the conversion
 | |
|   // to T. This allows testing that the transparent operations are correctly
 | |
|   // forwarding the SearchedType all the way to this comparison by checking
 | |
|   // that we didn't have a conversion when we search for a SearchedType<T>
 | |
|   // in a container full of StoredType<T>.
 | |
|   friend bool operator==(StoredType const& lhs, SearchedType<T> const& rhs) {
 | |
|     return lhs.value_ == rhs.get_value();
 | |
|   }
 | |
|   friend bool operator==(SearchedType<T> const& lhs, StoredType<T> const& rhs) {
 | |
|     return lhs.get_value() == rhs.value_;
 | |
|   }
 | |
| 
 | |
|   int get_value() const {
 | |
|     return value_;
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   T value_;
 | |
| };
 | |
| 
 | |
| #endif // TEST_STD_VER > 17
 | |
| 
 | |
| #endif // TRANSPARENT_H
 |