%PDF- %PDF-
Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/base/ |
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/base/template-utils.h |
// Copyright 2017 the V8 project 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 V8_BASE_TEMPLATE_UTILS_H_ #define V8_BASE_TEMPLATE_UTILS_H_ #include <array> #include <functional> #include <iosfwd> #include <tuple> #include <type_traits> #include <utility> namespace v8 { namespace base { namespace detail { template <typename Function, std::size_t... Indexes> constexpr inline auto make_array_helper(Function f, std::index_sequence<Indexes...>) -> std::array<decltype(f(0)), sizeof...(Indexes)> { return {{f(Indexes)...}}; } } // namespace detail // base::make_array: Create an array of fixed length, initialized by a function. // The content of the array is created by calling the function with 0 .. Size-1. // Example usage to create the array {0, 2, 4}: // std::array<int, 3> arr = base::make_array<3>( // [](std::size_t i) { return static_cast<int>(2 * i); }); // The resulting array will be constexpr if the passed function is constexpr. template <std::size_t Size, class Function> constexpr auto make_array(Function f) { return detail::make_array_helper(f, std::make_index_sequence<Size>{}); } // Helper to determine how to pass values: Pass scalars and arrays by value, // others by const reference (even if it was a non-const ref before; this is // disallowed by the style guide anyway). // The default is to also remove array extends (int[5] -> int*), but this can be // disabled by setting {remove_array_extend} to false. template <typename T, bool remove_array_extend = true> struct pass_value_or_ref { using noref_t = typename std::remove_reference<T>::type; using decay_t = typename std::conditional< std::is_array<noref_t>::value && !remove_array_extend, noref_t, typename std::decay<noref_t>::type>::type; using type = typename std::conditional<std::is_scalar<decay_t>::value || std::is_array<decay_t>::value, decay_t, const decay_t&>::type; }; // Uses expression SFINAE to detect whether using operator<< would work. template <typename T, typename TStream = std::ostream, typename = void> struct has_output_operator : std::false_type {}; template <typename T, typename TStream> struct has_output_operator< T, TStream, decltype(void(std::declval<TStream&>() << std::declval<T>()))> : std::true_type {}; // Turn std::tuple<A...> into std::tuple<A..., T>. template <class Tuple, class T> using append_tuple_type = decltype(std::tuple_cat( std::declval<Tuple>(), std::declval<std::tuple<T>>())); // Turn std::tuple<A...> into std::tuple<T, A...>. template <class T, class Tuple> using prepend_tuple_type = decltype(std::tuple_cat( std::declval<std::tuple<T>>(), std::declval<Tuple>())); namespace detail { template <size_t N, typename Tuple> constexpr bool NIsNotGreaterThanTupleSize = N <= std::tuple_size_v<std::decay_t<Tuple>>; template <size_t N, typename T, size_t... Ints> constexpr auto tuple_slice_impl(const T& tpl, std::index_sequence<Ints...>) { return std::tuple{std::get<N + Ints>(tpl)...}; } template <typename Tuple, typename Function, size_t... Index> constexpr auto tuple_for_each_impl(const Tuple& tpl, Function&& function, std::index_sequence<Index...>) { (function(std::get<Index>(tpl)), ...); } template <typename Tuple, typename Function, size_t... Index> constexpr auto tuple_for_each_with_index_impl(const Tuple& tpl, Function&& function, std::index_sequence<Index...>) { (function(std::get<Index>(tpl), std::integral_constant<size_t, Index>()), ...); } } // namespace detail // Get the first N elements from a tuple. template <size_t N, typename Tuple> constexpr auto tuple_head(Tuple&& tpl) { constexpr size_t total_size = std::tuple_size_v<std::decay_t<Tuple>>; static_assert(N <= total_size); return detail::tuple_slice_impl<0>(std::forward<Tuple>(tpl), std::make_index_sequence<N>()); } // Drop the first N elements from a tuple. template < size_t N, typename Tuple, // If the user accidentally passes in an N that is larger than the tuple // size, the unsigned subtraction will create a giant index sequence and // crash the compiler. To avoid this and fail early, disable this function // for invalid N. typename = std::enable_if_t<detail::NIsNotGreaterThanTupleSize<N, Tuple>>> constexpr auto tuple_drop(Tuple&& tpl) { constexpr size_t total_size = std::tuple_size_v<std::decay_t<Tuple>>; static_assert(N <= total_size); return detail::tuple_slice_impl<N>( std::forward<Tuple>(tpl), std::make_index_sequence<total_size - N>()); } // Calls `function(v)` for each `v` in the tuple. template <typename Tuple, typename Function> constexpr void tuple_for_each(Tuple&& tpl, Function&& function) { detail::tuple_for_each_impl( std::forward<Tuple>(tpl), function, std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>()); } // Calls `function(v, i)` for each `v` in the tuple, with index `i`. The index // `i` is passed as an std::integral_constant<size_t>, rather than a raw size_t, // to allow it to be used template <typename Tuple, typename Function> constexpr void tuple_for_each_with_index(Tuple&& tpl, Function&& function) { detail::tuple_for_each_with_index_impl( std::forward<Tuple>(tpl), function, std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>()); } #ifdef __clang__ template <size_t N, typename... Ts> using nth_type = __type_pack_element<N, Ts...>; #else template <size_t N, typename... Ts> struct nth_type; template <typename T, typename... Ts> struct nth_type<0, T, Ts...> { using type = T; }; template <size_t N, typename T, typename... Ts> struct nth_type<N, T, Ts...> : public nth_type<N - 1, Ts...> {}; #endif template <size_t N, typename... T> using nth_type_t = typename nth_type<N, T...>::type; // Find SearchT in Ts. SearchT must be present at most once in Ts, and returns // sizeof...(Ts) if not found. template <typename SearchT, typename... Ts> struct index_of_type; // Not found / empty list. template <typename SearchT> struct index_of_type<SearchT> : public std::integral_constant<size_t, 0> {}; // SearchT found at head of list. template <typename SearchT, typename... Ts> struct index_of_type<SearchT, SearchT, Ts...> : public std::integral_constant<size_t, 0> { // SearchT is not allowed to be anywhere else in the list. static_assert(index_of_type<SearchT, Ts...>::value == sizeof...(Ts)); }; // Recursion, SearchT not found at head of list. template <typename SearchT, typename T, typename... Ts> struct index_of_type<SearchT, T, Ts...> : public std::integral_constant<size_t, 1 + index_of_type<SearchT, Ts...>::value> { }; template <typename SearchT, typename... Ts> constexpr size_t index_of_type_v = index_of_type<SearchT, Ts...>::value; } // namespace base } // namespace v8 #endif // V8_BASE_TEMPLATE_UTILS_H_