• 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 TStream = std::ostream, typename = void>
57 struct has_output_operator : std::false_type {};
58 template <typename T, typename TStream>
59 struct has_output_operator<
60     T, TStream, decltype(void(std::declval<TStream&>() << std::declval<T>()))>
61     : std::true_type {};
62 
63 }  // namespace base
64 }  // namespace v8
65 
66 #endif  // V8_BASE_TEMPLATE_UTILS_H_
67