Info
-
Did you know DRY (Don’t Repeat Yourself) comparisons pattern?
Example
auto none_of(auto pred, auto... ts) {
const auto a = std::array{ts...};
return std::none_of(std::cbegin(a), std::cend(a), pred);
}
auto before(int a, int b, int c) {
if (a != 2 and b != 2 and c != 2) {
return 42;
}
return 0;
}
auto after(int a, int b, int c) {
if (none_of([](auto x) { return x == 2; }, a, b, c)) {
return 42;
}
return 0;
}
Puzzle
Can you implement DRY version of
any_of
with user-friendly interface?
/* TODO any_of */
int main() {
using namespace boost::ut;
should("return true if any of given values is equal the expected value") = [] {
expect(any_of(1) == 1);
expect(any_of(1, 2, 3) == 2);
expect(any_of(1, 2, 3) == 3);
};
should("return false if all of given values do not equal the expected value") = [] {
expect(not (any_of() == 0));
expect(not (any_of(1) == 42));
expect(not (any_of(2) == 42));
expect(not (any_of(1, 2, 3) == 42));
};
}
Solutions
#include <utility>
#include <tuple>
#include <concepts>
template<class ... Args>
struct Comp {
template<class T>
auto operator==(T && other) {
return std::apply(
[&other](auto &&... data) {
return (((std::equality_comparable_with<decltype(data), T>) && data == other) || ...);
},
this -> data
);
}
std::tuple<Args...> data {};
};
template<class ...Args>
auto any_of(Args && ... args) {
return Comp<Args...> {
std::make_tuple(std::forward<Args>(args)...)
};
}
template <class... Ts>
struct any_of {
any_of(Ts... args) : args{args...} {}
auto operator==(auto rhs) const {
return std::apply([&](auto... lhs) { return (... or (lhs == rhs)); }, args);
}
private:
std::tuple<Ts...> args;
};
template <typename ... Ts>
struct any_of{
any_of(Ts const & ... args):t(args...){}
bool operator==(auto const & i) {
return std::apply( [&i](auto const & ...args){
return ((args==i)||...);
}
, t
);
}
std::tuple<Ts...> t;
};
template<typename T=int, typename ... Vs>
class any_of {
std::array<T, sizeof ... (Vs)> values;
public:
any_of (Vs ... vs) {
if constexpr (sizeof ... (Vs)) {
this->values = std::array{vs...};
}
}
constexpr bool operator==(const T& other) {
return std::any_of(
std::cbegin(this->values),
std::cend(this->values),
[&other](auto x) { return x == other; } );
}
}
template <typename... Ts>
struct any_of {
any_of(Ts... ts):values{ts...}{}
auto operator == (auto t){
return std::any_of(std::begin(values), std::end(values), [=](auto x){ return t == x;});
}
private:
std::array<int, sizeof...(Ts)> values;
};
template <class... Ts>
struct any_of {
any_of(Ts... values) : values_{values...} {}
bool operator==(auto to) const {
return std::apply([&](auto&&... value) { return ((value == to) || ...); }, values_);
}
private:
std::tuple<Ts...> values_;
};