//===----------------------------------------------------------------------===// // // 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 // for std::equal_to // testing transparent #if TEST_STD_VER > 11 struct transparent_less { template constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept(std::forward(t) < std::forward(u))) -> decltype (std::forward(t) < std::forward(u)) { return std::forward(t) < std::forward(u); } using is_transparent = void; // correct }; struct transparent_less_not_referenceable { template constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept(std::forward(t) < std::forward(u))) -> decltype (std::forward(t) < std::forward(u)) { return std::forward(t) < std::forward(u); } using is_transparent = void () const &; // it's a type; a weird one, but a type }; struct transparent_less_no_type { template constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept(std::forward(t) < std::forward(u))) -> decltype (std::forward(t) < std::forward(u)) { return std::forward(t) < std::forward(u); } private: // using is_transparent = void; // error - should exist }; struct transparent_less_private { template constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept(std::forward(t) < std::forward(u))) -> decltype (std::forward(t) < std::forward(u)) { return std::forward(t) < std::forward(u); } private: using is_transparent = void; // error - should be accessible }; struct transparent_less_not_a_type { template constexpr auto operator()(T&& t, U&& u) const noexcept(noexcept(std::forward(t) < std::forward(u))) -> decltype (std::forward(t) < std::forward(u)) { return std::forward(t) < std::forward(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 struct StoredType; template struct SearchedType; struct hash_impl { template constexpr std::size_t operator()(SearchedType const& t) const { return static_cast(t.get_value()); } template constexpr std::size_t operator()(StoredType const& t) const { return static_cast(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 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() const { ++*conversions_; return StoredType{value_}; } int get_value() const { return value_; } private: T value_; int* conversions_; }; template 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 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 // in a container full of StoredType. friend bool operator==(StoredType const& lhs, SearchedType const& rhs) { return lhs.value_ == rhs.get_value(); } friend bool operator==(SearchedType const& lhs, StoredType 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