View in context in the libbitcoin Slack #general mirror.
template <typename Functor>
struct for_each
{
template <size_t Index = zero, typename... Args,
if_lesser<Index, array_count<argument<zero, Args...>>> = true>
static constexpr void unroll(Args&... args) noexcept
{
static_assert(!is_zero(array_count<argument<zero, Args...>>));
Functor::fn(args[Index]...);
if constexpr (Index != sub1(array_count<argument<zero, Args...>>))
{
unroll<add1(Index)>(args...);
}
}
};
struct xor2
{
static constexpr void fn(auto& x, auto y) noexcept
{
x ^= y;
}
};
// static_assert helper.
template <size_t Offset = zero>
constexpr auto zeroize2(auto a) noexcept
{
auto copy{ a };
for_each<xor2>::unroll<Offset>(copy, a);
return copy;
}
static_assert(zeroize2(set3{ 1, 2, 3 }) == set3{ 0, 0, 0 });
static_assert(zeroize2<0>(set3{ 1, 2, 3 }) == set3{ 0, 0, 0 });
static_assert(zeroize2<1>(set3{ 1, 2, 3 }) == set3{ 1, 0, 0 });
static_assert(zeroize2<2>(set3{ 1, 2, 3 }) == set3{ 1, 2, 0 });
static_assert(zeroize2<3>(set3{ 1, 2, 3 }) == set3{ 1, 2, 3 });