Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static_assert with nonconstexpr objects in hana's tutorial

Reading the hana's tutorial, I wonder how can that static_assert work as expected:

template <typename Any>
auto switch_(Any& a) {
  return [&a](auto ...cases_) {
    auto cases = hana::make_tuple(cases_...);

    auto default_ = hana::find_if(cases, [](auto const& c) {
      return hana::first(c) == hana::type_c<default_t>;
    });

    static_assert(default_ != hana::nothing,
      "switch is missing a default_ case");

    // ...
  };
}

The documentation explicitly states that default_ is not a constexpr object, so, even if the overload of operator!= for those types is a constexpr function, the expression default_ != hana::nothing cannot be a constant expression since one of its arguments isn't.

The tutorial says:

Notice how we can use static_assert on the result of the comparison with nothing, even though default_ is a non-constexpr object? Boldly, Hana makes sure that no information that's known at compile-time is lost to the runtime, which is clearly the case of the presence of a default_ case.

What does the tutorial refer to with that paragraph, or how does that expression work?

like image 859
Peregring-lk Avatar asked Oct 15 '25 18:10

Peregring-lk


1 Answers

You misunderstand what constexpr requires. You can pass non-constexpr args to a constexpr function, and the result can be constexpr.

A toy example:

struct foo {
  int x;
  foo(int in):x(in){}
  friend constexpr bool operator==(foo const&, foo const&) { return true; }
};

then

foo a{1}, b{2};
static_assert( a==b, "works" );

is perfectly valid.

Heck, I could allocate those foo on the heap, and == would still evaluate as a constexpr expression.

default_ is not constexpr, but comparing it with nothing can be done using only the type information of default_, which is available at compile time. Nothing compares equal to hana::nothing but (another instance of) nothing.

struct toy_nothing_t {
  friend constexpr bool operator==(toy_nothing_t const&, toy_nothing_t const&) {
    return true;
  }
  template<class T>
  friend constexpr bool operator==(T const&, toy_nothing_t const&) {
    return false;
  }
  template<class T>
  friend constexpr bool operator==(toy_nothing_t const&, T const&) {
    return false;
  }
};

this toy_nothing_t has similar properties.

like image 140
Yakk - Adam Nevraumont Avatar answered Oct 17 '25 13:10

Yakk - Adam Nevraumont



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!