272.md
September 5, 2022 ยท View on GitHub
Info
-
Did you know that C++20 added std::ranges::{all_of, any_of, none_of} algorithms?
Example
int main() {
assert(std::ranges::all_of (std::array{1, 1, 1}, [](const auto& value) { return value == 1; }));
assert(std::ranges::any_of (std::array{1, 2, 3}, [](const auto& value) { return value == 2; }));
assert(std::ranges::none_of(std::array{1, 2, 3}, [](const auto& value) { return value == 4; }));
}
Puzzle
- Can you implement consteval equivalents of {all_of, any_of, none_of} algorithms?
template<auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool; // TODO
template<auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool; // TODO
template<auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool; // TODO
static_assert(all_of([](auto v) { return v == 1; }));
static_assert(all_of<1, 1, 1>([](auto v) { return v == 1; }));
static_assert(all_of<1>([](auto v) { return v == 1; }));
static_assert(not all_of<1, 2, 1>([](auto v) { return v == 1; }));
static_assert(not all_of<1, 2>([](auto v) { return v == 1; }));
static_assert(not all_of<1, 2>([](auto v) { return v == 2; }));
static_assert(any_of<1, 2, 3>([](auto v) { return v == 1; }));
static_assert(any_of<1, 2, 3>([](auto v) { return v == 2; }));
static_assert(any_of<1, 2, 3>([](auto v) { return v == 3; }));
static_assert(any_of<1>([](auto v) { return v == 1; }));
static_assert(not any_of([](auto v) { return v == 1; }));
static_assert(not any_of<1, 2, 3>([](auto v) { return v == 0; }));
static_assert(not any_of<1, 2, 3>([](auto v) { return v == 4; }));
static_assert(none_of([](auto v) { return v == 1; }));
static_assert(none_of<1, 2, 3>([](auto v) { return v == 0; }));
static_assert(none_of<1, 2, 3>([](auto v) { return v == 4; }));
static_assert(none_of<1, 1, 1>([](auto v) { return v == 2; }));
static_assert(not none_of<1>([](auto v) { return v == 1; }));
static_assert(not none_of<1, 2, 3>([](auto v) { return v == 1; }));
static_assert(not none_of<1, 2, 3>([](auto v) { return v == 2; }));
static_assert(not none_of<1, 2, 3>([](auto v) { return v == 3; }));
Solutions
template<auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool {
return (expr(Values) && ...);
}
template<auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool {
return (expr(Values) || ...);
}
template<auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool {
return !(expr(Values) || ...);
}
template<auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool
{
if constexpr (sizeof...(Values) > 0)
return std::ranges::all_of(std::array{Values...}, expr);
return true;
}
template<auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool
{
if constexpr (sizeof...(Values) > 0)
return std::ranges::any_of(std::array{Values...}, expr);
return false;
}
template<auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool
{
if constexpr (sizeof...(Values) > 0)
return std::ranges::none_of(std::array{Values...}, expr);
return true;
}
template<auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool {
return (expr(Values) and ...);
}
template<auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool {
return (expr(Values) or ...);
}
template<auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool {
return not (expr(Values) or ...);
}
template <auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool {
return (... and expr(Values));
}
template <auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool {
return (... or expr(Values));
}
template <auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool {
return not any_of<Values...>(expr);
}
template<auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool {
return (expr(Values) and ...);
}
template<auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool {
return (expr(Values) or ...);
}
template<auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool {
return not any_of<Values...>(expr);
}
template <auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool {
return (... and expr(Values));
}
template <auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool {
return (... or expr(Values));
}
template <auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool {
return not any_of<Values...>(expr);
}
template<auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool {
if constexpr(sizeof...(Values)) return std::ranges::all_of(std::array{Values...}, expr);
return true;
}
template<auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool {
if constexpr (sizeof...(Values)) return std::ranges::any_of(std::array{Values...}, expr);
return false;
}
template<auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool {
if constexpr(sizeof...(Values)) return std::ranges::none_of(std::array{Values...}, expr);
return true;
}
template<auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool {
return std::ranges::all_of(std::array<int, sizeof...(Values)>{Values...}, expr);
}
template<auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool {
return std::ranges::any_of(std::array<int, sizeof...(Values)>{Values...}, expr);
}
template<auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool {
return std::ranges::none_of(std::array<int, sizeof...(Values)>{Values...}, expr);
}
template<auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool{
if constexpr (sizeof...(Values) == 0) return true;
else
return std::ranges::all_of(std::array<std::common_type_t<decltype(Values)...>, sizeof...(Values)>{{Values...}}, expr);
}
template<auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool{
if constexpr (sizeof...(Values) == 0) return false;
else
return std::ranges::any_of(std::array<std::common_type_t<decltype(Values)...>, sizeof...(Values)>{{Values...}}, expr);
}
template<auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool{
if constexpr (sizeof...(Values) == 0) return true;
else
return std::ranges::none_of(std::array<std::common_type_t<decltype(Values)...>, sizeof...(Values)>{{Values...}}, expr);
}
template<auto... Values>
[[nodiscard]] consteval auto all_of(auto expr) -> bool {
return (expr(Values) & ... & true) ;
}
template<auto... Values>
[[nodiscard]] consteval auto any_of(auto expr) -> bool {
return (expr(Values) || ... || false);
}
template<auto... Values>
[[nodiscard]] consteval auto none_of(auto expr) -> bool {
return ( (not expr(Values)) & ... & true);
}