Line data Source code
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 <memory>
10 :
11 : namespace v8 {
12 : namespace base {
13 :
14 : namespace detail {
15 :
16 : // make_array_helper statically iteratively creates the index list 0 .. Size-1.
17 : // A specialization for the base case (first index is 0) finally constructs the
18 : // array.
19 : // TODO(clemensh): Use std::index_sequence once we have C++14 support.
20 : template <class Function, std::size_t... Indexes>
21 : struct make_array_helper;
22 :
23 : template <class Function, std::size_t... Indexes>
24 : struct make_array_helper<Function, 0, Indexes...> {
25 : constexpr static auto make_array(Function f)
26 : -> std::array<decltype(f(std::size_t{0})), sizeof...(Indexes) + 1> {
27 : return {{f(0), f(Indexes)...}};
28 : }
29 : };
30 :
31 : template <class Function, std::size_t FirstIndex, std::size_t... Indexes>
32 : struct make_array_helper<Function, FirstIndex, Indexes...>
33 : : make_array_helper<Function, FirstIndex - 1, FirstIndex, Indexes...> {};
34 :
35 : } // namespace detail
36 :
37 : // base::make_array: Create an array of fixed length, initialized by a function.
38 : // The content of the array is created by calling the function with 0 .. Size-1.
39 : // Example usage to create the array {0, 2, 4}:
40 : // std::array<int, 3> arr = base::make_array<3>(
41 : // [](std::size_t i) { return static_cast<int>(2 * i); });
42 : // The resulting array will be constexpr if the passed function is constexpr.
43 : template <std::size_t Size, class Function>
44 : constexpr auto make_array(Function f)
45 : -> std::array<decltype(f(std::size_t{0})), Size> {
46 : static_assert(Size > 0, "Can only create non-empty arrays");
47 : return detail::make_array_helper<Function, Size - 1>::make_array(f);
48 : }
49 :
50 : // base::make_unique<T>: Construct an object of type T and wrap it in a
51 : // std::unique_ptr.
52 : // Replacement for C++14's std::make_unique.
53 : template <typename T, typename... Args>
54 314733 : std::unique_ptr<T> make_unique(Args&&... args) {
55 630456 : return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
56 : }
57 :
58 : // implicit_cast<A>(x) triggers an implicit cast from {x} to type {A}. This is
59 : // useful in situations where static_cast<A>(x) would do too much.
60 : template <class A>
61 : A implicit_cast(A x) {
62 : return x;
63 : }
64 :
65 : // Helper to determine how to pass values: Pass scalars and arrays by value,
66 : // others by const reference (even if it was a non-const ref before; this is
67 : // disallowed by the style guide anyway).
68 : // The default is to also remove array extends (int[5] -> int*), but this can be
69 : // disabled by setting {remove_array_extend} to false.
70 : template <typename T, bool remove_array_extend = true>
71 : struct pass_value_or_ref {
72 : using noref_t = typename std::remove_reference<T>::type;
73 : using decay_t = typename std::conditional<
74 : std::is_array<noref_t>::value && !remove_array_extend, noref_t,
75 : typename std::decay<noref_t>::type>::type;
76 : using type = typename std::conditional<std::is_scalar<decay_t>::value ||
77 : std::is_array<decay_t>::value,
78 : decay_t, const decay_t&>::type;
79 : };
80 :
81 : template <typename T>
82 : struct has_output_operator {
83 : // This template is only instantiable if U provides operator<< with ostream.
84 : // Its return type is uint8_t.
85 : template <typename U>
86 : static auto __check_operator(U u)
87 : -> decltype(*(std::ostream*)nullptr << *u, uint8_t{0});
88 : // This is a fallback implementation, returning uint16_t. If the template
89 : // above is instantiable, is has precedence over this varargs function.
90 : static uint16_t __check_operator(...);
91 :
92 : using ptr_t = typename std::add_pointer<T>::type;
93 : static constexpr bool value = sizeof(__check_operator(ptr_t{nullptr})) == 1;
94 : };
95 :
96 : } // namespace base
97 : } // namespace v8
98 :
99 : #endif // V8_BASE_TEMPLATE_UTILS_H
|