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?

+3


source to share


1 answer


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 :: fold_left example

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) | ...); }
  );
};

      

hana :: unpack example

+2


source







All Articles