Commit 24aa162d authored by Pádraig Ó Conbhuí's avatar Pádraig Ó Conbhuí
Browse files

Initial Commit.

parents
This diff is collapsed.
#include <utility>
#include <tuple>
namespace visit_bools {
namespace detail {
template<size_t... N, typename Callback, typename ArgsTuple>
constexpr decltype(auto) invoke_tuple(
std::index_sequence<N...>, Callback&& callback, ArgsTuple&& args
) {
return callback(std::get<N>(std::forward<ArgsTuple>(args))...);
}
template<typename Callback, typename ArgsTuple>
constexpr decltype(auto) visit_bools_impl(Callback&& callback, ArgsTuple&& args) {
return invoke_tuple(
std::make_index_sequence<std::tuple_size<ArgsTuple>::value>(),
callback, args
);
}
template<typename TupleHead, typename Callback, typename... Args>
constexpr decltype(auto) visit_bools_impl(
Callback&& callback, TupleHead&& head, bool arg, Args&&... args
);
template<typename TupleHead, typename Callback, typename Arg, typename... Args>
constexpr decltype(auto) visit_bools_impl(
Callback&& callback, TupleHead&& head, Arg&& arg,
Args&&... args
) {
return visit_bools_impl(
std::forward<Callback>(callback),
std::tuple_cat(
std::forward<TupleHead>(head),
std::forward_as_tuple(std::forward<Arg>(arg))
),
std::forward<Args>(args)...
);
}
template<typename TupleHead, typename Callback, typename... Args>
constexpr decltype(auto) visit_bools_impl(
Callback&& callback, TupleHead&& head, bool arg,
Args&&... args
) {
if(arg) {
return visit_bools_impl(
std::forward<Callback>(callback),
std::tuple_cat(
std::forward<TupleHead>(head),
std::forward_as_tuple(std::true_type{})
),
std::forward<Args>(args)...
);
}
else {
return visit_bools_impl(
std::forward<Callback>(callback),
std::tuple_cat(
std::forward<TupleHead>(head),
std::forward_as_tuple(std::false_type{})
),
std::forward<Args>(args)...
);
}
}
} // namespace detail
template<typename Callable, typename... Args>
constexpr decltype(auto) visit_bools(Callable&& callable, Args&&... args) {
return detail::visit_bools_impl(
std::forward<Callable>(callable),
std::tuple<>(),
std::forward<Args>(args)...
);
}
} // namespace visit_bools
#include "visit_bools.hpp"
#define CATCH_CONFIG_MAIN
#include "external/catch2/catch/catch.hpp"
int static_value(std::true_type) { return 1; }
int static_value(std::false_type) { return 0; }
TEST_CASE("visit_bools", "[visit_bools]") {
bool a = GENERATE(true, false);
bool b = GENERATE(true, false);
bool c = GENERATE(true, false);
SECTION("visit_bools with only bools") {
auto value = visit_bools::visit_bools([](auto a, auto b, auto c) {
return 2*2*static_value(a)
+ 2*static_value(b)
+ static_value(c);
}, a, b, c);
REQUIRE(value == (2*2*(a?1:0) + 2*(b?1:0) + (c?1:0)));
}
SECTION("visit_bools with mixed values") {
float d = GENERATE(10.1f, 20.2f);
float value;
SECTION("mixed first") {
auto tmp_value = visit_bools::visit_bools(
[](auto d, auto a, auto b, auto c) {
return 2*2*static_value(a)
+ 2*static_value(b)
+ static_value(c)
+ d;
},
d, a, b, c
);
value = tmp_value;
STATIC_REQUIRE(std::is_same<decltype(tmp_value), float>::value);
}
SECTION("mixed second") {
auto tmp_value = visit_bools::visit_bools(
[](auto a, auto d, auto b, auto c) {
return 2*2*static_value(a)
+ 2*static_value(b)
+ static_value(c)
+ d;
},
a, d, b, c
);
value = tmp_value;
STATIC_REQUIRE(std::is_same<decltype(tmp_value), float>::value);
}
SECTION("mixed last") {
auto tmp_value = visit_bools::visit_bools(
[](auto a, auto b, auto c, auto d) {
return 2*2*static_value(a)
+ 2*static_value(b)
+ static_value(c)
+ d;
},
a, b, c, d
);
value = tmp_value;
STATIC_REQUIRE(std::is_same<decltype(tmp_value), float>::value);
}
REQUIRE(value == (2*2*(a?1:0) + 2*(b?1:0) + (c?1:0)) + d);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment