Search code examples
c++metaprogrammingc++17boost-hana

struct member and boost::hana::filter


Faced typical novice problem with constexpr modifier in modern c++.

Am I right that there's no way to write such code even in c++17 (cause of http://www.boost.org/doc/libs/1_63_0/libs/hana/doc/html/index.html#tutorial-appendix-constexpr)?

And one must use "value as a type" idiom (use different types for Open and Closed files in this example)?

#include <boost/hana/filter.hpp>
#include <boost/hana/tuple.hpp>

namespace hana = boost::hana;

enum class State {
  Open, Closed
};

struct File {
  constexpr File(State state) : state_(state) {}

  constexpr State state() const { return state_; }

  const State state_;
};

constexpr auto files = hana::make_tuple(File(State::Closed), File(State::Open));
constexpr auto filtered = hana::filter(files, [](const auto& file) {
  return file.state() == State::Open;
});

int main() {
  return 0;
}

Solution

  • In the lambda that you pass to hana::filter, you have two problems:

    1. The file parameter is not constexpr
    2. The return value is not a compile-time IntegralConstant convertible to bool as is required by hana::filter.

    One way to keep your tuple elements constexpr in any context is to wrap them in constexpr lambdas (added in C++17).

    The following code addresses both issues:

    constexpr auto files = hana::make_tuple(
      []{ return File(State::Closed); }
    , []{ return File(State::Open); }
    );
    
    constexpr auto filtered = hana::filter(files, [](auto file) {
      return hana::bool_c<file().state() == State::Open>;
    });