blob: 415b3acf1c9a4bef492b5b616f0a8508e1f89d72 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2011 The Chromium Authors
willchan@chromium.org951269b2010-06-15 19:39:242// 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_TEMPLATE_UTIL_H_
6#define BASE_TEMPLATE_UTIL_H_
willchan@chromium.org951269b2010-06-15 19:39:247
danakja26bdfc2016-04-13 22:08:038#include <stddef.h>
Avi Drissman02aadae12022-05-04 02:50:489
jbroman6bcfec422016-05-26 00:28:4610#include <iosfwd>
Brett Wilson322a5462017-08-03 23:59:1211#include <iterator>
tzik403cb6c2016-03-10 07:17:2512#include <type_traits>
danakja26bdfc2016-04-13 22:08:0313#include <utility>
ajwong@chromium.orgb38d3572011-02-15 01:27:3814
Jan Wilken Dörrie2d7bca02021-04-19 19:59:3215#include "base/compiler_specific.h"
willchan@chromium.org792cdcf2010-12-15 09:55:3516
willchan@chromium.org951269b2010-06-15 19:39:2417namespace base {
18
danakja26bdfc2016-04-13 22:08:0319namespace internal {
20
jbroman6bcfec422016-05-26 00:28:4621// Uses expression SFINAE to detect whether using operator<< would work.
22template <typename T, typename = void>
23struct SupportsOstreamOperator : std::false_type {};
24template <typename T>
25struct SupportsOstreamOperator<T,
26 decltype(void(std::declval<std::ostream&>()
27 << std::declval<T>()))>
28 : std::true_type {};
29
Collin Baker89e9e072019-06-10 22:39:0530template <typename T, typename = void>
31struct SupportsToString : std::false_type {};
32template <typename T>
33struct SupportsToString<T, decltype(void(std::declval<T>().ToString()))>
34 : std::true_type {};
35
Brett Wilson322a5462017-08-03 23:59:1236// Used to detech whether the given type is an iterator. This is normally used
37// with std::enable_if to provide disambiguation for functions that take
38// templatzed iterators as input.
39template <typename T, typename = void>
40struct is_iterator : std::false_type {};
41
42template <typename T>
Avi Drissman1089236e2022-04-28 13:44:4143struct is_iterator<
44 T,
45 std::void_t<typename std::iterator_traits<T>::iterator_category>>
Brett Wilson322a5462017-08-03 23:59:1246 : std::true_type {};
47
Jan Wilken Dörrie9f8955f2020-09-16 10:27:1848// Helper to express preferences in an overload set. If more than one overload
49// are available for a given set of parameters the overload with the higher
50// priority will be chosen.
51template <size_t I>
52struct priority_tag : priority_tag<I - 1> {};
53
54template <>
55struct priority_tag<0> {};
56
danakja26bdfc2016-04-13 22:08:0357} // namespace internal
58
Jan Wilken Dörrief89fc2ac2021-03-05 06:51:2259namespace internal {
60
61// The indirection with std::is_enum<T> is required, because instantiating
62// std::underlying_type_t<T> when T is not an enum is UB prior to C++20.
63template <typename T, bool = std::is_enum<T>::value>
64struct IsScopedEnumImpl : std::false_type {};
65
66template <typename T>
67struct IsScopedEnumImpl<T, /*std::is_enum<T>::value=*/true>
Avi Drissmanc109efd2022-04-27 22:03:3568 : std::negation<std::is_convertible<T, std::underlying_type_t<T>>> {};
Jan Wilken Dörrief89fc2ac2021-03-05 06:51:2269
70} // namespace internal
71
72// Implementation of C++23's std::is_scoped_enum
73//
74// Reference: https://en.cppreference.com/w/cpp/types/is_scoped_enum
75template <typename T>
76struct is_scoped_enum : internal::IsScopedEnumImpl<T> {};
77
Jan Wilken Dörrie94bb5bc2021-03-22 18:37:4078// Implementation of C++20's std::remove_cvref.
79//
80// References:
81// - https://en.cppreference.com/w/cpp/types/remove_cvref
82// - https://wg21.link/meta.trans.other#lib:remove_cvref
83template <typename T>
84struct remove_cvref {
85 using type = std::remove_cv_t<std::remove_reference_t<T>>;
86};
87
88// Implementation of C++20's std::remove_cvref_t.
89//
90// References:
91// - https://en.cppreference.com/w/cpp/types/remove_cvref
92// - https://wg21.link/meta.type.synop#lib:remove_cvref_t
93template <typename T>
94using remove_cvref_t = typename remove_cvref<T>::type;
95
Jan Wilken Dörrie9f8955f2020-09-16 10:27:1896// Simplified implementation of C++20's std::iter_value_t.
97// As opposed to std::iter_value_t, this implementation does not restrict
98// the type of `Iter` and does not consider specializations of
99// `indirectly_readable_traits`.
100//
101// Reference: https://wg21.link/readable.traits#2
102template <typename Iter>
danakj6948b8722022-05-04 14:02:04103struct IterValueImpl {
104 using value_type = typename std::iterator_traits<Iter>::value_type;
105};
106
107template <typename T, bool Cond = false>
108struct IterValuePointerImpl {
109 // The `iterator_traits<T*>::value_type` member is not defined if T is not an
110 // object in C++20.
111};
112template <typename T>
113struct IterValuePointerImpl<T*, true> {
114 using value_type = typename std::iterator_traits<T*>::value_type;
115};
116
117template <typename T>
118struct IterValueImpl<T*> {
119 using value_type =
120 typename IterValuePointerImpl<T*, std::is_object_v<T>>::value_type;
121};
122
123template <typename Iter>
124using iter_value_t = typename IterValueImpl<remove_cvref_t<Iter>>::value_type;
Jan Wilken Dörrie9f8955f2020-09-16 10:27:18125
126// Simplified implementation of C++20's std::iter_reference_t.
127// As opposed to std::iter_reference_t, this implementation does not restrict
128// the type of `Iter`.
129//
130// Reference: https://wg21.link/iterator.synopsis#:~:text=iter_reference_t
131template <typename Iter>
132using iter_reference_t = decltype(*std::declval<Iter&>());
133
134// Simplified implementation of C++20's std::indirect_result_t. As opposed to
135// std::indirect_result_t, this implementation does not restrict the type of
136// `Func` and `Iters`.
137//
138// Reference: https://wg21.link/iterator.synopsis#:~:text=indirect_result_t
139template <typename Func, typename... Iters>
Avi Drissman67c3b1e2022-04-27 20:42:49140using indirect_result_t =
141 std::invoke_result_t<Func, iter_reference_t<Iters>...>;
Jan Wilken Dörrie9f8955f2020-09-16 10:27:18142
143// Simplified implementation of C++20's std::projected. As opposed to
144// std::projected, this implementation does not explicitly restrict the type of
145// `Iter` and `Proj`, but rather does so implicitly by requiring
146// `indirect_result_t<Proj, Iter>` is a valid type. This is required for SFINAE
147// friendliness.
148//
149// Reference: https://wg21.link/projected
150template <typename Iter,
151 typename Proj,
152 typename IndirectResultT = indirect_result_t<Proj, Iter>>
153struct projected {
Jan Wilken Dörrie94bb5bc2021-03-22 18:37:40154 using value_type = remove_cvref_t<IndirectResultT>;
Jan Wilken Dörrie9f8955f2020-09-16 10:27:18155
156 IndirectResultT operator*() const; // not defined
157};
158
willchan@chromium.org951269b2010-06-15 19:39:24159} // namespace base
160
dpolukhin@chromium.org81e8ebf2010-09-16 07:59:27161#endif // BASE_TEMPLATE_UTIL_H_