[base] Reimplement {base::fold} in C++14

Just two functions instead of partially specialized structs. Also, no
need to compute the return type(s), just use {auto}.

R=tebbi@chromium.org

Bug: v8:9396
Change-Id: I840af52c3caac622aded8bd7656a5437abb2c8ef
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1801845
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63756}
This commit is contained in:
Clemens Hammacher 2019-09-13 15:10:24 +02:00 committed by Commit Bot
parent 46f9d4008a
commit e651ab6ff6

View File

@ -58,38 +58,17 @@ struct has_output_operator<T, decltype(void(std::declval<std::ostream&>()
<< std::declval<T>()))>
: std::true_type {};
namespace detail {
template <typename Func, typename T, typename... Ts>
struct fold_helper {
static_assert(sizeof...(Ts) == 0, "this is the base case");
using result_t = typename std::remove_reference<T>::type;
static constexpr T&& fold(Func func, T&& first) {
return std::forward<T>(first);
}
};
// Fold all arguments from left to right with a given function.
template <typename Func, typename T>
constexpr auto fold(Func func, T&& t) {
return std::forward<T>(t);
}
template <typename Func, typename T1, typename T2, typename... Ts>
struct fold_helper<Func, T1, T2, Ts...> {
using folded_t = typename std::result_of<Func(T1, T2)>::type;
using next_fold_helper = fold_helper<Func, folded_t&&, Ts...>;
using result_t = typename next_fold_helper::result_t;
static constexpr result_t fold(Func func, T1&& first, T2&& second,
Ts&&... more) {
return next_fold_helper::fold(
func, func(std::forward<T1>(first), std::forward<T2>(second)),
std::forward<Ts>(more)...);
}
};
} // namespace detail
// Fold all arguments from left to right with a given function.
template <typename Func, typename... Ts>
constexpr auto fold(Func func, Ts&&... more) ->
typename detail::fold_helper<Func, Ts...>::result_t {
return detail::fold_helper<Func, Ts...>::fold(func,
std::forward<Ts>(more)...);
constexpr auto fold(Func func, T1&& first, T2&& second, Ts&&... more) {
auto&& folded = func(std::forward<T1>(first), std::forward<T2>(second));
return fold(std::move(func), std::forward<decltype(folded)>(folded),
std::forward<Ts>(more)...);
}
// {is_same<Ts...>::value} is true if all Ts are the same, false otherwise.