Search code examples
c++boostc++17autoboost-hana

Using hana filter on tuple of types: "use of boost::hana::not_equal_t before deduction of auto"


I'm trying to filter a hana::tuple_t, which from my understanding is just a hana::tuple of hana::type objects.

I looked at some code from the example in the documentation, which is:

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");
    auto rest = hana::filter(cases, [](auto const& c) {
      return hana::first(c) != hana::type_c<default_t>;
    });
    // ...
  };
}

In this case (again, if my understanding is correct), cases is a hana::tuple of hana::pair objects, where the first element in the pair is a hana::type object.

So here is my code, which should work the same way:

#include <boost/hana/tuple.hpp>
#include <boost/hana/filter.hpp>
namespace hana = boost::hana;

int main() {
    auto types_tuple = hana::tuple_t<int, float, char>;
    auto filtered_tuple = hana::filter(types_tuple, [](auto const & type) {
        return type != hana::type_c<float>;
    });
}

The goal here being for filtered_tuple to end up being the same as hana::tuple_t<int, char>.

This does not compile. I get a long compiler output, but the relevant part (I think) is:

/usr/include/boost/hana/detail/operators/comparable.hpp: In instantiation of ‘constexpr auto boost::hana::detail::operators::operator!=(X&&, Y&&) [with X = boost::hana::type_impl<int>::_&; Y = const boost::hana::type_impl<float>::_&; <template-parameter-1-3> = void]’:
/path/to/test.cpp:9:21:   required from ‘main()::<lambda(auto:1)> [with auto:1 = boost::hana::type_impl<int>::_]’
/usr/include/boost/hana/filter.hpp:105:34:   required by substitution of ‘template<class ... X> boost::hana::detail::filter_indices<static_cast<bool>(boost::hana::detail::decay<decltype((((const boost::hana::detail::make_filter_indices<main::__lambda0>*)this)->boost::hana::detail::make_filter_indices<main::__lambda0>::pred)(static_cast<X&>(boost::hana::detail::make_filter_indices::operator()::x))), typename std::remove_reference<decltype((((const boost::hana::detail::make_filter_indices<main::__lambda0>*)this)->boost::hana::detail::make_filter_indices<main::__lambda0>::pred)(static_cast<X&>(boost::hana::detail::make_filter_indices::operator()::x)))>::type>::type::value) ...> boost::hana::detail::make_filter_indices<main()::<lambda(auto:1)> >::operator()<X ...>(X&& ...) const [with X = {boost::hana::type_impl<int>::_&, boost::hana::type_impl<float>::_&, boost::hana::type_impl<std::__cxx11::basic_string<char> >::_&}]’
/usr/include/boost/hana/basic_tuple.hpp:117:39:   required from ‘static constexpr decltype(auto) boost::hana::unpack_impl<boost::hana::basic_tuple_tag>::apply(boost::hana::detail::basic_tuple_impl<std::integer_sequence<long unsigned int, _Idx ...>, Xn ...>&, F&&) [with long unsigned int ...i = {0, 1, 2}; Xn = {boost::hana::type_impl<int>::_, boost::hana::type_impl<float>::_, boost::hana::type_impl<std::__cxx11::basic_string<char> >::_}; F = boost::hana::detail::make_filter_indices<main()::<lambda(auto:1)> >]’
/usr/include/boost/hana/unpack.hpp:47:29:   required from ‘constexpr decltype(auto) boost::hana::unpack_t::operator()(Xs&&, F&&) const [with Xs = boost::hana::basic_tuple<boost::hana::type_impl<int>::_, boost::hana::type_impl<float>::_, boost::hana::type_impl<std::__cxx11::basic_string<char> >::_>&; F = boost::hana::detail::make_filter_indices<main()::<lambda(auto:1)> >]’
/usr/include/boost/hana/tuple.hpp:225:32:   required from ‘static constexpr decltype(auto) boost::hana::unpack_impl<boost::hana::tuple_tag>::apply(Xs&&, F&&) [with Xs = boost::hana::tuple<boost::hana::type_impl<int>::_, boost::hana::type_impl<float>::_, boost::hana::type_impl<std::__cxx11::basic_string<char> >::_>&; F = boost::hana::detail::make_filter_indices<main()::<lambda(auto:1)> >]’
/usr/include/boost/hana/unpack.hpp:47:29:   required from ‘constexpr decltype(auto) boost::hana::unpack_t::operator()(Xs&&, F&&) const [with Xs = boost::hana::tuple<boost::hana::type_impl<int>::_, boost::hana::type_impl<float>::_, boost::hana::type_impl<std::__cxx11::basic_string<char> >::_>&; F = boost::hana::detail::make_filter_indices<main()::<lambda(auto:1)> >]’
/usr/include/boost/hana/filter.hpp:123:29:   required from ‘static constexpr auto boost::hana::filter_impl<S, boost::hana::when<boost::hana::Sequence<S>::value> >::apply(Xs&&, const Pred&) [with Xs = boost::hana::tuple<boost::hana::type_impl<int>::_, boost::hana::type_impl<float>::_, boost::hana::type_impl<std::__cxx11::basic_string<char> >::_>&; Pred = main()::<lambda(auto:1)>; S = boost::hana::tuple_tag]’
/usr/include/boost/hana/filter.hpp:48:29:   required from ‘constexpr auto boost::hana::filter_t::operator()(Xs&&, Pred&&) const [with Xs = boost::hana::tuple<boost::hana::type_impl<int>::_, boost::hana::type_impl<float>::_, boost::hana::type_impl<std::__cxx11::basic_string<char> >::_>&; Pred = main()::<lambda(auto:1)>]’
/path/to/test.cpp:10:6:   required from here
/usr/include/boost/hana/detail/operators/comparable.hpp:40:33: error: use of ‘constexpr auto boost::hana::not_equal_t::operator()(X&&, Y&&) const [with X = boost::hana::type_impl<int>::_&; Y = const boost::hana::type_impl<float>::_&]’ before deduction of ‘auto’
         { return hana::not_equal(static_cast<X&&>(x), static_cast<Y&&>(y)); }
                  ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I'm using Boost 1.65.1 and C++17.

Why doesn't my code work? From what I've seen, "use of some function returning auto before deduction of auto" usually comes from recursion, like in this post, which makes sense. But there's no recursion here. There is also this post which seems closely related to my issue, but it's not exactly the same and the answer doesn't help me.


Solution

  • You're only missing an #include: <boost/hana/not_equal.hpp>.

    Online Demo