[base] Remove base::fold and base::all

They can be replaced by std::conjunction and c++17 folding expressions.

R=tebbi@chromium.org

Bug: v8:12425
Change-Id: I109ac904245aab431f11752eff5129fd4361de8a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3570428
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79843}
This commit is contained in:
Clemens Backes 2022-04-07 10:12:16 +02:00 committed by V8 LUCI CQ
parent 16b5fc3c57
commit 9f128f4e9f
5 changed files with 9 additions and 97 deletions

View File

@ -60,19 +60,6 @@ struct has_output_operator<
T, TStream, decltype(void(std::declval<TStream&>() << std::declval<T>()))>
: std::true_type {};
// 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>
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.
template <typename... Ts>
struct is_same : public std::false_type {};
@ -83,12 +70,6 @@ struct is_same<T> : public std::true_type {};
template <typename T, typename... Ts>
struct is_same<T, T, Ts...> : public is_same<T, Ts...> {};
// Returns true, iff all values (implicitly converted to bool) are trueish.
template <typename... Args>
constexpr bool all(Args... rest) {
return fold(std::logical_and<>{}, true, rest...);
}
} // namespace base
} // namespace v8

View File

@ -26,12 +26,8 @@ class V8_EXPORT_PRIVATE CPURegList {
public:
template <typename... CPURegisters>
explicit CPURegList(CPURegister reg0, CPURegisters... regs)
: list_(base::fold(
[](uint64_t acc, CPURegister v) {
if (!v.is_valid()) return acc;
return acc | (uint64_t{1} << v.code());
},
0, reg0, regs...)),
: list_(((uint64_t{1} << reg0.code()) | ... |
(regs.is_valid() ? uint64_t{1} << regs.code() : 0))),
size_(reg0.SizeInBits()),
type_(reg0.type()) {
DCHECK(AreSameSizeAndType(reg0, regs...));

View File

@ -20,22 +20,14 @@ constexpr bool ShouldPadArguments(int argument_count) {
}
#ifdef DEBUG
struct CountIfValidRegisterFunctor {
template <typename RegType>
constexpr int operator()(int count, RegType reg) const {
return count + (reg.is_valid() ? 1 : 0);
}
};
template <typename RegType, typename... RegTypes,
template <typename... RegTypes,
// All arguments must be either Register or DoubleRegister.
typename = typename std::enable_if<
base::is_same<Register, RegType, RegTypes...>::value ||
base::is_same<DoubleRegister, RegType, RegTypes...>::value>::type>
inline constexpr bool AreAliased(RegType first_reg, RegTypes... regs) {
int num_different_regs = RegListBase<RegType>{first_reg, regs...}.Count();
int num_given_regs =
base::fold(CountIfValidRegisterFunctor{}, 0, first_reg, regs...);
base::is_same<Register, RegTypes...>::value ||
base::is_same<DoubleRegister, RegTypes...>::value>::type>
inline constexpr bool AreAliased(RegTypes... regs) {
int num_different_regs = RegListBase{regs...}.Count();
int num_given_regs = (... + (regs.is_valid() ? 1 : 0));
return num_different_regs < num_given_regs;
}
#endif

View File

@ -70,7 +70,7 @@ class V8_EXPORT_PRIVATE Graph final : public NON_EXPORTED_BASE(ZoneObject) {
// for argument types convertible to Node* during overload resolution.
template <typename... Nodes,
typename = typename std::enable_if_t<
base::all(std::is_convertible<Nodes, Node*>::value...)>>
std::conjunction_v<std::is_convertible<Nodes, Node*>...>>>
Node* NewNode(const Operator* op, Nodes... nodes) {
std::array<Node*, sizeof...(nodes)> nodes_arr{
{static_cast<Node*>(nodes)...}};

View File

@ -107,63 +107,6 @@ static_assert(has_output_operator<TestClass3>::value,
static_assert(has_output_operator<const TestClass3>::value,
"const TestClass3 can be output");
//////////////////////////////
// Test fold.
//////////////////////////////
struct FoldAllSameType {
constexpr uint32_t operator()(uint32_t a, uint32_t b) const { return a | b; }
};
static_assert(base::fold(FoldAllSameType{}, 3, 6) == 7, "check fold");
// Test that it works if implicit conversion is needed for one of the
// parameters.
static_assert(base::fold(FoldAllSameType{}, uint8_t{1}, 256) == 257,
"check correct type inference");
// Test a single parameter.
static_assert(base::fold(FoldAllSameType{}, 25) == 25,
"check folding a single argument");
TEST(TemplateUtilsTest, FoldDifferentType) {
auto fn = [](std::string str, char c) {
str.push_back(c);
return str;
};
CHECK_EQ(base::fold(fn, std::string("foo"), 'b', 'a', 'r'), "foobar");
}
TEST(TemplateUtilsTest, FoldMoveOnlyType) {
auto fn = [](std::unique_ptr<std::string> str, char c) {
str->push_back(c);
return str;
};
std::unique_ptr<std::string> str = std::make_unique<std::string>("foo");
std::unique_ptr<std::string> folded =
base::fold(fn, std::move(str), 'b', 'a', 'r');
CHECK_NULL(str);
CHECK_NOT_NULL(folded);
CHECK_EQ(*folded, "foobar");
}
struct TemplatizedFoldFunctor {
template <typename T, typename... Tup>
std::tuple<Tup..., typename std::decay<T>::type> operator()(
std::tuple<Tup...> tup, T&& val) {
return std::tuple_cat(std::move(tup),
std::make_tuple(std::forward<T>(val)));
}
};
TEST(TemplateUtilsTest, FoldToTuple) {
auto input = std::make_tuple(char{'x'}, int{4}, double{3.2},
std::unique_ptr<uint8_t>{}, std::string{"foo"});
auto result =
base::fold(TemplatizedFoldFunctor{}, std::make_tuple(),
std::get<0>(input), std::get<1>(input), std::get<2>(input),
std::unique_ptr<uint8_t>{}, std::get<4>(input));
static_assert(std::is_same<decltype(result), decltype(input)>::value,
"the resulting tuple should have the same type as the input");
DCHECK_EQ(input, result);
}
} // namespace template_utils_unittest
} // namespace base
} // namespace v8