How to remove metaprogramming relaying with Boost Hana
I am trying to create a bitset according to the dispatch type of the function. But shrink the test case a bit.
Warning . I'm using the auto gcc extension for this example, I don't need to use a template parameter.
namespace hana = boost::hana;
constexpr decltype(auto) rec(auto i, auto max, auto f, auto returnValue) {
return returnValue |= f(i);
if constexpr (i < max) //"infinite" loop if no constexpr
return rec(i + hana::size_c<1>, max, f, returnValue);
else
return returnValue;
}
constexpr decltype(auto) foo(auto ct, auto ... type) {
constexpr auto tuple = hana::make_tuple(type...);
constexpr unsigned long returnValue = 0L;
constexpr auto f = [tuple, ct] (auto i) {
if (hana::contains(tuple, ct[i]))
return 0 << decltype(i)::value;
else
return 0;
};
return rec(hana::size_c<0>, hana::size_c<3>, f, returnValue);
}
struct T1 {};
struct T2 {};
struct T3 {};
int main () {
constexpr auto t1 = hana::type_c<T1>;
constexpr auto t2 = hana::type_c<T2>;
constexpr auto t3 = hana::type_c<T3>;
constexpr auto ct = hana::make_tuple(t1, t2, t3);
constexpr auto test = foo(ct, t1, t2);
}
It looks like my tuple is not considered a search tuple, but if I try the same hana :: contains outside the lambda, I have no problem.
The whole bug is huge, so check it out: live demo
By the way, I tried to do it using a for loop but couldn't. Do you know a good way to do things like this in C ++ 17/20?
source to share
The error was caused by an out of bounds access caused by using manual recursion. Part of the goal of functional programming is to provide constructs to eliminate the possibility of such errors.
Here are some examples, but it is recommended to take a look at the concept guide hana::Foldable
as it is really based on using Boost.Hana.
hana::fold_left
hides the recursion for you, and can reduce the number of recursive calls with quick tracking:
constexpr decltype(auto) foo = [](auto ct, auto ... type) {
constexpr auto tuple = hana::make_tuple(type...);
return hana::fold_left(hana::make_range(hana::size_c<0>, hana::size_c<3>), 0L,
[tuple, ct](auto returnValue, auto i)
{
// returnValue param is not constexpr
if (hana::contains(tuple, ct[i])) {
return returnValue | (1 << decltype(i)::value);
}
else
{
return returnValue;
}
}
);
};
hana::unpack
eliminates recursion entirely using the variation package extension:
constexpr decltype(auto) foo = [](auto ct, auto ... type) {
constexpr auto tuple = hana::make_tuple(type...);
auto f = [tuple, ct](auto i)
{
return hana::contains(tuple, ct[i]) ? (1 << decltype(i)::value) : 0;
};
return hana::unpack(hana::make_range(hana::size_c<0>, hana::size_c<3>),
[f](auto ...i) { return (f(i) | ...); }
);
};
source to share