summaryrefslogtreecommitdiff
path: root/chromium/base/parameter_pack.h
blob: 9e09fb3d83b0eb554ab69e90f6ffb0c4149a7b84 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_PARAMETER_PACK_H_
#define BASE_PARAMETER_PACK_H_

#include <stddef.h>

#include <initializer_list>
#include <tuple>
#include <type_traits>

#include "base/template_util.h"
#include "build/build_config.h"

namespace base {

// Checks if any of the elements in |ilist| is true.
// Similar to std::any_of for the case of constexpr initializer_list.
inline constexpr bool any_of(std::initializer_list<bool> ilist) {
  for (auto c : ilist) {
    if (c)
      return true;
  }
  return false;
}

// Checks if all of the elements in |ilist| are true.
// Similar to std::all_of for the case of constexpr initializer_list.
inline constexpr bool all_of(std::initializer_list<bool> ilist) {
  for (auto c : ilist) {
    if (!c)
      return false;
  }
  return true;
}

// Counts the elements in |ilist| that are equal to |value|.
// Similar to std::count for the case of constexpr initializer_list.
template <class T>
inline constexpr size_t count(std::initializer_list<T> ilist, T value) {
  size_t c = 0;
  for (const auto& v : ilist) {
    c += (v == value);
  }
  return c;
}

template <class... Ts >
struct if_all;

template <>
struct if_all<>
    : std::integral_constant<bool, true> {};

template <class T, class... Ts >
struct if_all<T, Ts...>
    : std::conditional<T::value, if_all<Ts...>, std::integral_constant<bool, false>>::type {};


template <class... Ts >
struct if_any;

template <>
struct if_any<>
    : std::integral_constant<bool, false> {};

template <class T, class... Ts >
struct if_any<T, Ts...>
    : std::conditional<T::value, std::integral_constant<bool, true>, if_any<Ts...>>::type {};

constexpr size_t pack_npos = -1;

template <typename... Ts>
struct ParameterPack {
  // Checks if |Type| occurs in the parameter pack.
  template <typename Type>
  using HasType = bool_constant<if_any<std::is_same<Type, Ts>...>::value>;

  // Checks if the parameter pack only contains |Type|.
  template <typename Type>
  using OnlyHasType = bool_constant<if_all<std::is_same<Type, Ts>...>::value>;

  // Breaks build with MSVC 2017 but it is not used.
#if !defined(COMPILER_MSVC)
  // Checks if |Type| occurs only once in the parameter pack.
  template <typename Type>
  using IsUniqueInPack =
      bool_constant<count({std::is_same<Type, Ts>::value...}, true) == 1>;
#endif

  // Returns the zero-based index of |Type| within |Pack...| or |pack_npos| if
  // it's not within the pack.
  template <typename Type>
  static constexpr size_t IndexInPack() {
    size_t index = 0;
    for (bool value : {std::is_same<Type, Ts>::value...}) {
      if (value)
        return index;
      index++;
    }
    return pack_npos;
  }

  // Helper for extracting the Nth type from a parameter pack.
  template <size_t N>
  using NthType = std::tuple_element_t<N, std::tuple<Ts...>>;

  // Checks if every type in the parameter pack is the same.
  using IsAllSameType =
      bool_constant<if_all<std::is_same<NthType<0>, Ts>...>::value>;
};

template <>
struct ParameterPack<> {
  // Checks if |Type| occurs in the parameter pack.
  template <typename Type>
  using HasType = bool_constant<false>;

  // Checks if the parameter pack only contains |Type|.
  template <typename Type>
  using OnlyHasType = bool_constant<true>;

  // Checks if |Type| occurs only once in the parameter pack.
  template <typename Type>
  using IsUniqueInPack = bool_constant<false>;

  // Returns the zero-based index of |Type| within |Pack...| or |pack_npos| if
  // it's not within the pack.
  template <typename Type>
  static constexpr size_t IndexInPack() {
    return pack_npos;
  }

  // Helper for extracting the Nth type from a parameter pack.
  template <size_t N>
  using NthType = void;

  // Checks if every type in the parameter pack is the same.
  using IsAllSameType =
      bool_constant<true>;
};

}  // namespace base

#endif  // BASE_PARAMETER_PACK_H_