tl;dr
I'd like to understand what's wrong with the first code below, i.e. what the error is telling me.
MRE
I've been able to shorten the example to the following, which generates the same error as the original code below:
#include <boost/hana/functional/overload.hpp>
auto l1 = [](int){}; using L1 = decltype(l1);
auto l2 = [](double){}; using L2 = decltype(l2);
auto l3 = [](float){}; using L3 = decltype(l3);
using Ovl = boost::hana::overload_t<L1, L2, L3>
//const // uncomment to prevent error
;
Ovl ovl{l1,l2,l3};
Ovl ovl2{ovl}; // this triggers the compilation error
Original question
I'm having trouble understanding the errors I get when I try partially applying std::visit
to a visitor function obtained via boost::hana::overload
. (I know that I can't pass around the name of a template function, so I can't really partially apply std::visit
, so I wrapped it in a generic lambda named just visit
; I've not bothered doing perfect forwarding because I hardly believe it's relevant to the question.)
#include <boost/hana/functional/overload.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/functional/curry.hpp>
#include <iomanip>
#include <iostream>
#include <variant>
#include <vector>
using var_t = std::variant<int, long, double, std::string>;
int main() {
std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
auto visitor = boost::hana::overload([](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; }
);
auto visit = [](auto const& visitor_, auto const&... visited_){
return std::visit(visitor_, visited_...);
};
for (auto& v: vec) {
boost::hana::partial(visit, visitor)(v); // the error is essentially
boost::hana::curry<2>(visit)(visitor)(v); // the same on these 2 lines
}
std::cout << std::endl;
}
The error is (godbolt):
In file included from deleteme.cpp:1:
/usr/include/boost/hana/functional/overload.hpp: In instantiation of ‘constexpr boost::hana::overload_t<F, G>::overload_t(F_&&, G_&& ...) [with F_ = boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >&; G_ = {}; F = main()::<lambda(auto:22)>; G = {main()::<lambda(double)>, main()::<lambda(const string&)>}]’:
/usr/include/boost/hana/detail/ebo.hpp:62:36: required from ‘constexpr _hana::ebo<K, V, true>::ebo(T&&) [with T = boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >&; K = boost::hana::detail::bti<1>; V = boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >]’
/usr/include/boost/hana/basic_tuple.hpp:70:65: required from ‘constexpr boost::hana::detail::basic_tuple_impl<std::integer_sequence<long unsigned int, _Idx ...>, Xn ...>::basic_tuple_impl(Yn&& ...) [with Yn = {main()::<lambda(const auto:25&, const auto:26& ...)>, boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >&}; long unsigned int ...n = {0, 1}; Xn = {main()::<lambda(const auto:25&, const auto:26& ...)>, boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >}]’
/usr/include/boost/hana/basic_tuple.hpp:97:44: required from ‘constexpr boost::hana::basic_tuple<Xs>::basic_tuple(Yn&& ...) [with Yn = {main()::<lambda(const auto:25&, const auto:26& ...)>, boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >&}; Xn = {main()::<lambda(const auto:25&, const auto:26& ...)>, boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >}]’
/usr/include/boost/hana/functional/partial.hpp:71:15: required from ‘constexpr boost::hana::partial_t<std::integer_sequence<long unsigned int, _Idx ...>, F, X ...>::partial_t(boost::hana::make_partial_t::secret, T&& ...) [with T = {main()::<lambda(const auto:25&, const auto:26& ...)>, boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >&}; long unsigned int ...n = {0}; F = main()::<lambda(const auto:25&, const auto:26& ...)>; X = {boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >}]’
/usr/include/boost/hana/functional/partial.hpp:61:74: required from ‘constexpr boost::hana::partial_t<std::integer_sequence<long unsigned int, __integer_pack()(sizeof ... (X ...))...>, typename boost::hana::detail::decay<Xs>::type, typename boost::hana::detail::decay<X, typename std::remove_reference<X>::type>::type ...> boost::hana::make_partial_t::operator()(F&&, X&& ...) const [with F = main()::<lambda(const auto:25&, const auto:26& ...)>; X = {boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >&}; typename boost::hana::detail::decay<Xs>::type = main()::<lambda(const auto:25&, const auto:26& ...)>; typename std::remove_reference<_Tp>::type = main()::<lambda(const auto:25&, const auto:26& ...)>]’
/usr/include/boost/hana/functional/curry.hpp:149:24: required from ‘constexpr decltype(auto) boost::hana::curry_t<n, F>::operator()(X&& ...) && [with X = {boost::hana::overload_t<main()::<lambda(auto:22)>, main()::<lambda(double)>, main()::<lambda(const string&)> >&}; long unsigned int n = 2; F = main()::<lambda(const auto:25&, const auto:26& ...)>]’
deleteme.cpp:31:37: required from here
/usr/include/boost/hana/functional/overload.hpp:53:61: error: no matching function for call to ‘boost::hana::overload_t<main()::<lambda(double)>, main()::<lambda(const string&)> >::overload_t()’
53 | , overload_t<G...>::type(static_cast<G_&&>(g)...)
| ^
/usr/include/boost/hana/functional/overload.hpp:51:28: note: candidate: ‘template<class F_, class ... G_> constexpr boost::hana::overload_t<F, G>::overload_t(F_&&, G_&& ...) [with F_ = F_; G_ = {G_ ...}; F = main()::<lambda(double)>; G = {main()::<lambda(const string&)>}]’
51 | constexpr explicit overload_t(F_&& f, G_&& ...g)
| ^~~~~~~~~~
/usr/include/boost/hana/functional/overload.hpp:51:28: note: template argument deduction/substitution failed:
/usr/include/boost/hana/functional/overload.hpp:53:61: note: candidate expects at least 1 argument, 0 provided
53 | , overload_t<G...>::type(static_cast<G_&&>(g)...)
| ^
/usr/include/boost/hana/functional/overload.hpp:42:12: note: candidate: ‘constexpr boost::hana::overload_t<main()::<lambda(double)>, main()::<lambda(const string&)> >::overload_t(const boost::hana::overload_t<main()::<lambda(double)>, main()::<lambda(const string&)> >&)’
42 | struct overload_t
| ^~~~~~~~~~
/usr/include/boost/hana/functional/overload.hpp:42:12: note: candidate expects 1 argument, 0 provided
/usr/include/boost/hana/functional/overload.hpp:42:12: note: candidate: ‘constexpr boost::hana::overload_t<main()::<lambda(double)>, main()::<lambda(const string&)> >::overload_t(boost::hana::overload_t<main()::<lambda(double)>, main()::<lambda(const string&)> >&&)’
/usr/include/boost/hana/functional/overload.hpp:42:12: note: candidate expects 1 argument, 0 provided
However, if I define visit
to be "manually" curried, it behaves as I expect (godbolt):
#include <boost/hana/functional/overload.hpp>
#include <boost/hana/functional/partial.hpp>
#include <boost/hana/functional/curry.hpp>
#include <iomanip>
#include <iostream>
#include <variant>
#include <vector>
// the variant to visit
using var_t = std::variant<int, long, double, std::string>;
int main() {
std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
auto visitor = boost::hana::overload([](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; }
);
auto visit_c = [](auto const& visitor_){
return [&visitor_](auto const&... visited_){
return std::visit(visitor_, visited_...);
};
};
for (auto& v: vec) {
visit_c(visitor)(v);
}
std::cout << std::endl;
}
(Example adapted from cppreference.)