Skip to content

hana::less does not work for adapted structs #530

Open
@PiotrNycz

Description

@PiotrNycz

Consider this code godbolt
The codebase is c++17 - so I cannot just default compare operators...

For any adapted struct (in hana (actually boost::hana) way) I have this strange situation when hana::equal just works for implementing operator== while hana::less cannot be used for implementing operator<. For me documentation is unclear - should it work?

I dig a little into this problem - and it seems that when I call directly hana::less from operator< then less calls operator< so infinite recursion - so segfault.
While when it is called directly (not via operator<) then it does not compile with a set of static-assert, starting from complaining about adapted struct being not ordered - well...

When I compared sources for equal and less - indeed - support for adapted structs is missing in less.

The code:

#include <boost/hana/adapt_struct.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/less.hpp>

namespace demo
{
struct Some
{
    int a;
    int b;
};
}

BOOST_HANA_ADAPT_STRUCT(demo::Some,
    a, b);

namespace demo
{
bool operator==(const Some& lhs, const Some& rhs)
{
    return boost::hana::equal(lhs, rhs);
}


bool less(const Some& lhs, const Some& rhs)
{
    return boost::hana::less(lhs, rhs);
}

bool operator<(const Some& lhs, const Some& rhs)
{
    // uncommenting boost::hana::less makes this segfault - because operator< calls itself
    //return boost::hana::less(lhs, rhs);
    return less(lhs, rhs);
}
}

int main() {
    return demo::Some{1, 1} < demo::Some{1, 2};
}

The output:

In file included from <source>:3:
/opt/compiler-explorer/libs/boost_1_84_0/boost/hana/less.hpp: In instantiation of 'constexpr auto boost::hana::less_t::operator()(X&&, Y&&) const [with X = const demo::Some&; Y = const demo::Some&]':
<source>:29:29:   required from here
/opt/compiler-explorer/libs/boost_1_84_0/boost/hana/less.hpp:51:43: error: static assertion failed: hana::less(x, y) requires 'x' to be Orderable
   51 |         static_assert(hana::Orderable<T>::value,
      |                                           ^~~~~
/opt/compiler-explorer/libs/boost_1_84_0/boost/hana/less.hpp:51:43: note: 'std::integral_constant<bool, false>::value' evaluates to false
/opt/compiler-explorer/libs/boost_1_84_0/boost/hana/less.hpp:54:43: error: static assertion failed: hana::less(x, y) requires 'y' to be Orderable
   54 |         static_assert(hana::Orderable<U>::value,
      |                                           ^~~~~
/opt/compiler-explorer/libs/boost_1_84_0/boost/hana/less.hpp:54:43: note: 'std::integral_constant<bool, false>::value' evaluates to false
/opt/compiler-explorer/libs/boost_1_84_0/boost/hana/less.hpp:57:53: error: static assertion failed: hana::less(x, y) requires 'x' and 'y' to be embeddable in a common Orderable
   57 |         static_assert(!is_default<less_impl<T, U>>::value,
      |                                                     ^~~~~
/opt/compiler-explorer/libs/boost_1_84_0/boost/hana/less.hpp:57:53: note: '!(bool)std::integral_constant<bool, true>::value' evaluates to false
/opt/compiler-explorer/libs/boost_1_84_0/boost/hana/less.hpp:62:27: error: use of deleted function 'static constexpr auto boost::hana::deleted_implementation::apply(T&& ...) [with T = {const demo::Some&, const demo::Some&}]'
   62 |         return Less::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
      |                ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/compiler-explorer/libs/boost_1_84_0/boost/hana/core/dispatch.hpp:14,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/hana/value.hpp:18,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/hana/concept/constant.hpp:19,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/hana/core/to.hpp:15,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/hana/bool.hpp:17,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/hana/string.hpp:15,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/hana/detail/struct_macros.hpp:28,
                 from /opt/compiler-explorer/libs/boost_1_84_0/boost/hana/adapt_struct.hpp:15,
                 from <source>:1:
/opt/compiler-explorer/libs/boost_1_84_0/boost/hana/detail/dispatch_if.hpp:21:31: note: declared here
   21 |         static constexpr auto apply(T&& ...) = delete;
      |                               ^~~~~
Compiler returned: 1

P.S.
I tried also to use hana::lexicographical_compare- but I did not manage to use it for adapted structs - any help would be welcome. I ended up with usinghana::all_of`...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions