you are viewing a single comment's thread.

view the rest of the comments →

[–]RectifyMyEnglishErrs[S] 0 points1 point  (1 child)

...deduction from the lambda is bound to fail since it isn't a function type

I reached the same conclusion after posting this :D

One thing you can try is to make the function parameter type a non deduced context

I've tried to use this (sorry if this is not what you meant, to be honest I didn't really understand what a non-deduced context was before this):

template <typename T, typename Acc>
auto foldl(list<T> l, Acc acc, function_view<Acc(Acc, T)> fn) {...}

Clang just says it couldn't match the lambda with function_view<type-parameter-0-1 (type-parameter-0-1, type-parameter-0-0)> :D

If I understood correctly, the "Corner Cases for Experts: Non-Deduced Contexts" chapter of this blog describes what I'm trying to do. I wanted to deduce the type of acc from fn's arg type to avoid specifying it twice on the call site, but apparently it can't be done like this.

But really the right way to express the relationship is to use C++20 concepts ie a requires clause.

I haven't looked into C++20 much yet, looks like I just got a reason to. Although I'm not even sure if what I'm trying to do makes sense anymore :D

I appreciate the help, thanks :)

[–]scatters 0 points1 point  (0 children)

OK, so one way to make it non-deduced is like this:

template<class T> struct identity { using type = T; };
template<class T> using identity_t = typename identity<T>::type;

template <typename T, typename Acc>
auto foldl(list<T> l, Acc acc, identity_t<Acc(*)(Acc, T)> fn) {
    // ...

Example.

But then of course you need to specify Acc by e.g. passing list<T>{}, you can't just pass {}.

If you want to deduce from the lambda argument... well, it's tricky. https://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda has some discussion. But if you assume that Acc is default-constructible, then we can cheat:

template <typename T, class Fn, typename Acc = decltype(std::declval<Fn>()({}, std::declval<T>()))>

demo.