1 //===- llvm/ADT/ilist_node_options.h - ilist_node Options -------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_ADT_ILIST_NODE_OPTIONS_H
10 #define LLVM_ADT_ILIST_NODE_OPTIONS_H
12 #include "llvm/Config/abi-breaking.h"
14 #include <type_traits>
18 template <bool EnableSentinelTracking
> class ilist_node_base
;
19 template <bool EnableSentinelTracking
> class ilist_base
;
21 /// Option to choose whether to track sentinels.
23 /// This option affects the ABI for the nodes. When not specified explicitly,
24 /// the ABI depends on LLVM_ENABLE_ABI_BREAKING_CHECKS. Specify explicitly to
25 /// enable \a ilist_node::isSentinel().
26 template <bool EnableSentinelTracking
> struct ilist_sentinel_tracking
{};
28 /// Option to specify a tag for the node type.
30 /// This option allows a single value type to be inserted in multiple lists
31 /// simultaneously. See \a ilist_node for usage examples.
32 template <class Tag
> struct ilist_tag
{};
34 namespace ilist_detail
{
36 /// Helper trait for recording whether an option is specified explicitly.
37 template <bool IsExplicit
> struct explicitness
{
38 static const bool is_explicit
= IsExplicit
;
40 typedef explicitness
<true> is_explicit
;
41 typedef explicitness
<false> is_implicit
;
43 /// Check whether an option is valid.
45 /// The steps for adding and enabling a new ilist option include:
46 /// \li define the option, ilist_foo<Bar>, above;
47 /// \li add new parameters for Bar to \a ilist_detail::node_options;
48 /// \li add an extraction meta-function, ilist_detail::extract_foo;
49 /// \li call extract_foo from \a ilist_detail::compute_node_options and pass it
50 /// into \a ilist_detail::node_options; and
51 /// \li specialize \c is_valid_option<ilist_foo<Bar>> to inherit from \c
52 /// std::true_type to get static assertions passing in \a simple_ilist and \a
54 template <class Option
> struct is_valid_option
: std::false_type
{};
56 /// Extract sentinel tracking option.
58 /// Look through \p Options for the \a ilist_sentinel_tracking option, with the
59 /// default depending on LLVM_ENABLE_ABI_BREAKING_CHECKS.
60 template <class... Options
> struct extract_sentinel_tracking
;
61 template <bool EnableSentinelTracking
, class... Options
>
62 struct extract_sentinel_tracking
<
63 ilist_sentinel_tracking
<EnableSentinelTracking
>, Options
...>
64 : std::integral_constant
<bool, EnableSentinelTracking
>, is_explicit
{};
65 template <class Option1
, class... Options
>
66 struct extract_sentinel_tracking
<Option1
, Options
...>
67 : extract_sentinel_tracking
<Options
...> {};
68 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
69 template <> struct extract_sentinel_tracking
<> : std::true_type
, is_implicit
{};
72 struct extract_sentinel_tracking
<> : std::false_type
, is_implicit
{};
74 template <bool EnableSentinelTracking
>
75 struct is_valid_option
<ilist_sentinel_tracking
<EnableSentinelTracking
>>
78 /// Extract custom tag option.
80 /// Look through \p Options for the \a ilist_tag option, pulling out the
81 /// custom tag type, using void as a default.
82 template <class... Options
> struct extract_tag
;
83 template <class Tag
, class... Options
>
84 struct extract_tag
<ilist_tag
<Tag
>, Options
...> {
87 template <class Option1
, class... Options
>
88 struct extract_tag
<Option1
, Options
...> : extract_tag
<Options
...> {};
89 template <> struct extract_tag
<> { typedef void type
; };
90 template <class Tag
> struct is_valid_option
<ilist_tag
<Tag
>> : std::true_type
{};
92 /// Check whether options are valid.
94 /// The conjunction of \a is_valid_option on each individual option.
95 template <class... Options
> struct check_options
;
96 template <> struct check_options
<> : std::true_type
{};
97 template <class Option1
, class... Options
>
98 struct check_options
<Option1
, Options
...>
99 : std::integral_constant
<bool, is_valid_option
<Option1
>::value
&&
100 check_options
<Options
...>::value
> {};
102 /// Traits for options for \a ilist_node.
104 /// This is usually computed via \a compute_node_options.
105 template <class T
, bool EnableSentinelTracking
, bool IsSentinelTrackingExplicit
,
107 struct node_options
{
108 typedef T value_type
;
110 typedef T
&reference
;
111 typedef const T
*const_pointer
;
112 typedef const T
&const_reference
;
114 static const bool enable_sentinel_tracking
= EnableSentinelTracking
;
115 static const bool is_sentinel_tracking_explicit
= IsSentinelTrackingExplicit
;
117 typedef ilist_node_base
<enable_sentinel_tracking
> node_base_type
;
118 typedef ilist_base
<enable_sentinel_tracking
> list_base_type
;
121 template <class T
, class... Options
> struct compute_node_options
{
122 typedef node_options
<T
, extract_sentinel_tracking
<Options
...>::value
,
123 extract_sentinel_tracking
<Options
...>::is_explicit
,
124 typename extract_tag
<Options
...>::type
>
128 } // end namespace ilist_detail
129 } // end namespace llvm
131 #endif // LLVM_ADT_ILIST_NODE_OPTIONS_H