Android-cuttlefish cvd tool
contains.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <algorithm>
20#include <iterator>
21#include <string>
22#include <string_view>
23#include <type_traits>
24
36namespace cuttlefish {
37namespace contains_internal_impl {
38
39/*
40 * If Container does not have find key, will be a compiler error used
41 * by SFINAE. If it does have one, this is equivalent to the "void" type.
42 */
43template <typename Container, typename Key>
45 decltype(void(std::declval<Container&>().find(std::declval<Key&>())));
46
47/*
48 * Here is how this works:
49 *
50 * Given that
51 * HasFindImpl<Container, T> is used in the code
52 *
53 * 1. The input is effectively regarded as HasFindImpl<Container, T, void>.
54 * The specialized version below isn't looked up yet; whether the specialized
55 * version below is used or not, the compiler front-end needs all three
56 * template parameters to match against either special or generic version.
57 * When obtaining "all three," the front-end only looks up the base template
58 * definition. The default type of the third template parameter is void, so
59 * the given type is expanded/deduced to HasFindImpl<Container, T, void>.
60 *
61 * 2. Now, given HasFindImpl<Container, T, void>, the compiler front-end
62 * tries matching against the specialized and generic/original versions. If
63 * the input could matches both a generic and a specialized one, the compiler
64 * chooses the specialized one. Thus, particularly, HasFindImpl
65 * implementation's third parameter in the specialized version must be the
66 * same as the default type of the third template parameter to the original/
67 * generic version, which is "void."
68 */
69template <typename Container, typename T, typename = void>
70struct HasFindImpl : std::false_type {};
71
72template <typename Container, typename T>
73struct HasFindImpl<Container, T, VoidTypeIfHasFind<Container, T>>
74 : std::true_type {};
75
76template <typename T>
78 typename std::remove_cv_t<typename std::remove_reference_t<T>>;
79
80template <typename T, typename U>
81using IsSame = typename std::is_same<RemoveCvref<T>, RemoveCvref<U>>;
82
83template <typename T>
84struct IsString : IsSame<std::string, T> {};
85
86template <typename T>
87struct IsStringView : IsSame<std::string_view, T> {};
88
89} // namespace contains_internal_impl
90
91// TODO(kwstephenkim): Replace these when C++20 starts to be used.
92template <typename Container, typename U,
93 typename = std::enable_if_t<
97 void>>
98constexpr bool Contains(Container&& container, U&& u) {
99 // using O(1) or O(lgN) find()
100 return container.find(std::forward<U>(u)) != container.end();
101}
102
103template <
104 typename Container, typename U,
105 std::enable_if_t<!contains_internal_impl::HasFindImpl<Container, U>::value,
106 int> = 0>
107constexpr bool Contains(Container&& container, U&& u) {
108 // falls back to a generic, likely linear search
109 const auto itr =
110 std::find(std::begin(container), std::end(container), std::forward<U>(u));
111 return itr != std::end(container);
112}
113
114// std::string:: or std::string_view::find() returns index, not iterator
115template <typename T>
116constexpr bool Contains(const std::string& s, T&& t) {
117 return s.find(std::forward<T>(t)) != std::string::npos;
118}
119
120template <typename T>
121constexpr bool Contains(const std::string_view& s, T&& t) {
122 return s.find(std::forward<T>(t)) != std::string_view::npos;
123}
124
125} // namespace cuttlefish
typename std::remove_cv_t< typename std::remove_reference_t< T > > RemoveCvref
Definition: contains.h:78
decltype(void(std::declval< Container & >().find(std::declval< Key & >()))) VoidTypeIfHasFind
Definition: contains.h:45
typename std::is_same< RemoveCvref< T >, RemoveCvref< U > > IsSame
Definition: contains.h:81
Definition: alloc_utils.cpp:23
constexpr bool Contains(Container &&container, U &&u)
Definition: contains.h:98