1 | //===- llvm/ADT/ADL.h - Argument dependent lookup utilities -----*- C++ -*-===// |
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 LLVM_ADT_ADL_H |
10 | #define LLVM_ADT_ADL_H |
11 | |
12 | #include <type_traits> |
13 | #include <iterator> |
14 | #include <utility> |
15 | |
16 | namespace llvm { |
17 | |
18 | // Only used by compiler if both template types are the same. Useful when |
19 | // using SFINAE to test for the existence of member functions. |
20 | template <typename T, T> struct SameType; |
21 | |
22 | namespace adl_detail { |
23 | |
24 | using std::begin; |
25 | |
26 | template <typename RangeT> |
27 | constexpr auto begin_impl(RangeT &&range) |
28 | -> decltype(begin(std::forward<RangeT>(range))) { |
29 | return begin(std::forward<RangeT>(range)); |
30 | } |
31 | |
32 | using std::end; |
33 | |
34 | template <typename RangeT> |
35 | constexpr auto end_impl(RangeT &&range) |
36 | -> decltype(end(std::forward<RangeT>(range))) { |
37 | return end(std::forward<RangeT>(range)); |
38 | } |
39 | |
40 | using std::swap; |
41 | |
42 | template <typename T> |
43 | constexpr void swap_impl(T &&lhs, |
44 | T &&rhs) noexcept(noexcept(swap(std::declval<T>(), |
45 | std::declval<T>()))) { |
46 | swap(std::forward<T>(lhs), std::forward<T>(rhs)); |
47 | } |
48 | |
49 | using std::size; |
50 | |
51 | template <typename RangeT> |
52 | constexpr auto size_impl(RangeT &&range) |
53 | -> decltype(size(std::forward<RangeT>(range))) { |
54 | return size(std::forward<RangeT>(range)); |
55 | } |
56 | |
57 | } // end namespace adl_detail |
58 | |
59 | /// Returns the begin iterator to \p range using `std::begin` and |
60 | /// function found through Argument-Dependent Lookup (ADL). |
61 | template <typename RangeT> |
62 | constexpr auto adl_begin(RangeT &&range) |
63 | -> decltype(adl_detail::begin_impl(std::forward<RangeT>(range))) { |
64 | return adl_detail::begin_impl(std::forward<RangeT>(range)); |
65 | } |
66 | |
67 | /// Returns the end iterator to \p range using `std::end` and |
68 | /// functions found through Argument-Dependent Lookup (ADL). |
69 | template <typename RangeT> |
70 | constexpr auto adl_end(RangeT &&range) |
71 | -> decltype(adl_detail::end_impl(std::forward<RangeT>(range))) { |
72 | return adl_detail::end_impl(std::forward<RangeT>(range)); |
73 | } |
74 | |
75 | /// Swaps \p lhs with \p rhs using `std::swap` and functions found through |
76 | /// Argument-Dependent Lookup (ADL). |
77 | template <typename T> |
78 | constexpr void adl_swap(T &&lhs, T &&rhs) noexcept( |
79 | noexcept(adl_detail::swap_impl(std::declval<T>(), std::declval<T>()))) { |
80 | adl_detail::swap_impl(std::forward<T>(lhs), std::forward<T>(rhs)); |
81 | } |
82 | |
83 | /// Returns the size of \p range using `std::size` and functions found through |
84 | /// Argument-Dependent Lookup (ADL). |
85 | template <typename RangeT> |
86 | constexpr auto adl_size(RangeT &&range) |
87 | -> decltype(adl_detail::size_impl(std::forward<RangeT>(range))) { |
88 | return adl_detail::size_impl(std::forward<RangeT>(range)); |
89 | } |
90 | |
91 | namespace detail { |
92 | |
93 | template <typename RangeT> |
94 | using IterOfRange = decltype(adl_begin(std::declval<RangeT &>())); |
95 | |
96 | template <typename RangeT> |
97 | using ValueOfRange = |
98 | std::remove_reference_t<decltype(*adl_begin(std::declval<RangeT &>()))>; |
99 | |
100 | } // namespace detail |
101 | } // namespace llvm |
102 | |
103 | #endif // LLVM_ADT_ADL_H |
104 | |