1 // Copyright 2021 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_CXX20_TO_ADDRESS_H_ 6 #define BASE_CXX20_TO_ADDRESS_H_ 7 8 #include <memory> 9 #include <type_traits> 10 11 namespace base { 12 13 namespace { 14 15 template <typename Ptr, typename = void> 16 struct has_std_to_address : std::false_type {}; 17 18 template <typename Ptr> 19 struct has_std_to_address< 20 Ptr, 21 std::void_t<decltype(std::pointer_traits<Ptr>::to_address( 22 std::declval<Ptr>()))>> : std::true_type {}; 23 24 } // namespace 25 26 // Implementation of C++20's std::to_address. 27 // Note: This does consider specializations of pointer_traits<>::to_address, 28 // even though it's a C++20 member function, because CheckedContiguousIterator 29 // specializes pointer_traits<> with a to_address() member. 30 // 31 // Reference: https://wg21.link/pointer.conversion#lib:to_address 32 template <typename T> 33 constexpr T* to_address(T* p) noexcept { 34 static_assert(!std::is_function<T>::value, 35 "Error: T must not be a function type."); 36 return p; 37 } 38 39 template <typename Ptr> 40 constexpr auto to_address(const Ptr& p) noexcept { 41 if constexpr (has_std_to_address<Ptr>::value) { 42 return std::pointer_traits<Ptr>::to_address(p); 43 } else { 44 return base::to_address(p.operator->()); 45 } 46 } 47 48 } // namespace base 49 50 #endif // BASE_CXX20_TO_ADDRESS_H_ 51