Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using `hana::is_valid` fails with const references

I am using hana to determine if an object has a Length member like so:

using boost::hana::is_valid;


static const auto has_length
    = is_valid([](const auto& obj)
            -> decltype(obj.Length(),void()) {});

This works fine....I can do static asserts with it all day to my hearts content. So the next step is logically to enable_if a function:

template<typename T>
auto foo(T t) -> std::enable_if_t<has_length(t), void>
{
}
struct mine
{
    int Length() const { return 0; }
};

int main()
{
    foo(mine{});
}

This works just fine....but as soon as I change the T to const T&, we get errors that there is no suitable overload: godbolt

So my question is: why does this happen?

like image 610
DarthRubik Avatar asked Sep 06 '25 03:09

DarthRubik


1 Answers

The problem is that calling a function with a reference that is not constexpr is not constexpr. This is where hana::is_valid is useful because it returns an integral_constant-like value that contains a static constexpr boolean so we can just look at the return type. See bool_.

Here is an example:

#include <boost/hana.hpp>
#include <type_traits>

namespace hana = boost::hana;

static auto has_length = hana::is_valid([](auto&& t)
  -> decltype(t.Length()) { });

template <typename T>
auto foo(T const& t)
  -> std::enable_if_t<decltype(has_length(t)){}, void>
                   // ^-- notice the return type 
                   // is a boolean integral constant
{ }

struct mine
{
  int Length() const { return 0; }
};

int main()
{
  foo(mine{});
}
like image 134
Jason Rice Avatar answered Sep 07 '25 23:09

Jason Rice