理解将部分函数应用程序或 curry 与重载和 std::visit 结合使用时的错误

问题描述

tl;博士

我想了解下面第一个代码有什么问题,即错误告诉我什么。

完整问题

当我尝试将 std::visit 部分应用于通过 boost::hana::overload 获得的访问者函数时,我无法理解所遇到的错误。 (我知道我不能传递模板函数的名称,所以我不能真正部分地应用 std::visit,所以我将它包装在一个名为 visit 的通用 lambda 中;我已经不费心做完美的转发,因为我几乎不相信它与问题相关。)

#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;
}

错误是 (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(const string&)> >&; K = boost::hana::detail::bti<1>; V = boost::hana::overload_t<main()::<lambda(auto:22)>,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(const string&)> >&}; long unsigned int ...n = {0,1}; Xn = {main()::<lambda(const auto:25&,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&,main()::<lambda(const string&)> >&}; Xn = {main()::<lambda(const auto:25&,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,F,X ...>::partial_t(boost::hana::make_partial_t::secret,T&& ...) [with T = {main()::<lambda(const auto:25&,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(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&,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(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_&& ...) [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

但是,如果我将 visit 定义为“手动”柯里化,它的行为与我预期的一样 (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,[](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;
}

(示例改编自 cppreference。)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)