• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_BASE_TEMPLATE_UTILS_H_
6 #define V8_BASE_TEMPLATE_UTILS_H_
7 
8 #include <array>
9 #include <functional>
10 #include <iosfwd>
11 #include <type_traits>
12 #include <utility>
13 
14 namespace v8 {
15 namespace base {
16 
17 namespace detail {
18 
19 template <typename Function, std::size_t... Indexes>
20 constexpr inline auto make_array_helper(Function f,
21                                         std::index_sequence<Indexes...>)
22     -> std::array<decltype(f(0)), sizeof...(Indexes)> {
23   return {{f(Indexes)...}};
24 }
25 
26 }  // namespace detail
27 
28 // base::make_array: Create an array of fixed length, initialized by a function.
29 // The content of the array is created by calling the function with 0 .. Size-1.
30 // Example usage to create the array {0, 2, 4}:
31 //   std::array<int, 3> arr = base::make_array<3>(
32 //       [](std::size_t i) { return static_cast<int>(2 * i); });
33 // The resulting array will be constexpr if the passed function is constexpr.
34 template <std::size_t Size, class Function>
make_array(Function f)35 constexpr auto make_array(Function f) {
36   return detail::make_array_helper(f, std::make_index_sequence<Size>{});
37 }
38 
39 // Helper to determine how to pass values: Pass scalars and arrays by value,
40 // others by const reference (even if it was a non-const ref before; this is
41 // disallowed by the style guide anyway).
42 // The default is to also remove array extends (int[5] -> int*), but this can be
43 // disabled by setting {remove_array_extend} to false.
44 template <typename T, bool remove_array_extend = true>
45 struct pass_value_or_ref {
46   using noref_t = typename std::remove_reference<T>::type;
47   using decay_t = typename std::conditional<
48       std::is_array<noref_t>::value && !remove_array_extend, noref_t,
49       typename std::decay<noref_t>::type>::type;
50   using type = typename std::conditional<std::is_scalar<decay_t>::value ||
51                                              std::is_array<decay_t>::value,
52                                          decay_t, const decay_t&>::type;
53 };
54 
55 // Uses expression SFINAE to detect whether using operator<< would work.
56 template <typename T, typename = void>
57 struct has_output_operator : std::false_type {};
58 template <typename T>
59 struct has_output_operator<T, decltype(void(std::declval<std::ostream&>()
60                                             << std::declval<T>()))>
61     : std::true_type {};
62 
63 // Fold all arguments from left to right with a given function.
64 template <typename Func, typename T>
65 constexpr auto fold(Func func, T&& t) {
66   return std::forward<T>(t);
67 }
68 
69 template <typename Func, typename T1, typename T2, typename... Ts>
70 constexpr auto fold(Func func, T1&& first, T2&& second, Ts&&... more) {
71   auto&& folded = func(std::forward<T1>(first), std::forward<T2>(second));
72   return fold(std::move(func), std::forward<decltype(folded)>(folded),
73               std::forward<Ts>(more)...);
74 }
75 
76 // {is_same<Ts...>::value} is true if all Ts are the same, false otherwise.
77 template <typename... Ts>
78 struct is_same : public std::false_type {};
79 template <>
80 struct is_same<> : public std::true_type {};
81 template <typename T>
82 struct is_same<T> : public std::true_type {};
83 template <typename T, typename... Ts>
84 struct is_same<T, T, Ts...> : public is_same<T, Ts...> {};
85 
86 // Returns true, iff all values (implicitly converted to bool) are trueish.
87 template <typename... Args>
88 constexpr bool all(Args... rest) {
89   return fold(std::logical_and<>{}, true, rest...);
90 }
91 
92 template <class... Ts>
93 struct make_void {
94   using type = void;
95 };
96 // Corresponds to C++17's std::void_t.
97 // Used for SFINAE based on type errors.
98 template <class... Ts>
99 using void_t = typename make_void<Ts...>::type;
100 
101 }  // namespace base
102 }  // namespace v8
103 
104 #endif  // V8_BASE_TEMPLATE_UTILS_H_
105