質問

I'm playing around with C++14 lambdas (well just lambdas in general really) and I have a function (pipeline) I'm trying to write. The premise is that it'll take a unit lambda and an array of unary lambdas that it'll then run on the unit and produce a new unit to send into the next in the pipeline until you get through the last lambda and return the final unit. my current code is:

auto pipeline = [](auto u, auto callbacks[]){
  for(int i = 0; i<sizeof(callbacks)/sizeof(callbacks[0]);i++){
     u = bind(u,callbacks[i]);
  }
  return u;
};

The current issue is that clang is kicking back on the array saying:

testFuture.cpp:183:111: error: no matching function for call to object of type 'func::<lambda at ./func.hpp:30:19>'
  cout<<"pipeline(unit(10),{addf(4),curry(mul,2)}):"<<bind(unit(bind(unit(10))(addf(4))))(curry(mul,2))<<"|"<<pipeline(unit(10),{{addf(4),curry(mul,2)}})()<<endl;
                                                                                                              ^~~~~~~~
./func.hpp:30:19: note: candidate template ignored: couldn't infer template argument '$auto-0-1'
  auto pipeline = [](auto u, auto callbacks[]){
                  ^
1 error generated.

Is this simply not possible with lambdas? Do I need to whip out std::function? Am I just going about this the wrong way?

役に立ちましたか?

解決

Taking a step back, you’re attempting to perform a (left) fold over a sequence of values. Because in C++ each closure has a unique type, you want to make that fold over a tuple, not an array. As an added benefit, we will be more general and accept functors with any return type, which we couldn’t if e.g. we used std::function to emulate arrow types.

#include <utility>      // std::forward, std::integer_sequence
#include <type_traits>  // std::remove_reference_t
#include <tuple>        // tuple protocol, e.g. std::get, std::tuple_size

namespace detail {

template<typename Functor, typename Zero, typename Tuple, typename Int>
Zero foldl(Functor&&, Zero&& zero, Tuple&&, std::integer_sequence<Int>)
{ return std::forward<Zero>(zero); }

template<typename Functor, typename Zero, typename Tuple, typename Int, Int Index, Int... Indices>
decltype(auto) foldl(Functor&& functor, Zero&& zero, Tuple&& tuple, std::integer_sequence<Int, Index, Indices...>)
{ return detail::foldl(
        functor
        , functor(std::forward<Zero>(zero), std::get<Index>(std::forward<Tuple>(tuple)))
        , std::forward<Tuple>(tuple)
        , std::integer_sequence<Int, Indices...> {}); }

} // detail

template<typename Functor, typename Zero, typename Tuple>
decltype(auto) foldl(Functor&& functor, Zero&& zero, Tuple&& tuple)
{
    return detail::foldl(
            std::forward<Functor>(functor)
            , std::forward<Zero>(zero)
            , std::forward<Tuple>(tuple)
            , std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value>()
            );
}

You haven’t told us what bind is supposed to achieve, but here’s an example involving reverse composition of functions. (Included is a limited implementation of integer_sequence and friends as they don’t appear to be available on Coliru — type traits aliases are missing as well.)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top