• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <type_traits>
17 
18 namespace pw::containers::internal {
19 
20 /// Crashes with a diagnostic message that intrusive containers must be empty
21 /// before destruction if the given `empty` parameter is not set.
22 ///
23 /// This function is standalone to avoid using PW_CHECK in a header file.
24 void CheckIntrusiveContainerIsEmpty(bool empty);
25 
26 /// Crashes with a diagnostic message that items must not be in an intrusive
27 /// container before insertion into an intrusive container or before destruction
28 /// if the given `uncontained` parameter is not set.
29 ///
30 /// This function is standalone to avoid using PW_CHECK in a header file.
31 void CheckIntrusiveItemIsUncontained(bool uncontained);
32 
33 // Gets the container's `value_type` from an item. This is used to check that an
34 // the `value_type` inherits from the container's nested `Item` type, either
35 // directly or through another class.
36 template <typename Item, typename T, bool kIsItem = std::is_base_of<Item, T>()>
37 struct IntrusiveItem {
38   using Type = void;
39 };
40 
41 // Items may be added to multiple containers, provided that they inherit from
42 // multiple base types, and that those types are disjoint.
43 template <typename Item, typename T>
44 struct IntrusiveItem<Item, T, true> {
45   using Type = typename T::ItemType;
46 };
47 
48 // Implementation of `is_weakly_orderable` that uses SFINE to detect when the
49 // given type can be ordered using the '<' operator.
50 template <typename T>
51 struct is_weakly_orderable_impl {
52   template <typename U>
53   static decltype(std::declval<U>() < std::declval<U>()) deduce(T*);
54 
55   template <typename>
56   static std::false_type deduce(...);
57 
58   using type = typename std::is_same<bool, decltype(deduce<T>(nullptr))>::type;
59 };
60 
61 /// Checks if a type can be compared with the less-than operator, '<'.
62 ///
63 /// If `T` satisfies \em LessThanComparable, provides the member constant
64 /// value equal to true. Otherwise value is false.
65 template <typename T>
66 struct is_weakly_orderable : is_weakly_orderable_impl<T>::type {};
67 
68 /// Helper variable template for `is_weakly_orderable<T>::value`.
69 template <typename T>
70 inline constexpr bool is_weakly_orderable_v = is_weakly_orderable<T>::value;
71 
72 }  // namespace pw::containers::internal
73