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