最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - How can I do boost::binary_traits with lambdas? - Stack Overflow

programmeradmin3浏览0评论

I'm trying to use boost::binary_traits to get the type of a functor's argument. It works for std::function but not for "lambda types".

#include <boost/functional.hpp>

template<typename Functor>
void foo(Functor&& f)
{
    boost::binary_traits<Functor>::first_argument_type a = 1; // error C2528: 'abstract declarator': pointer to reference is illegal
}

void bar()
{
    auto func1 = [](int i, int j) { return j; };
    std::function<int(int, int)> func2 = [](int i, int j) { return j; };
    foo(func1);
    boost::binary_traits<decltype(func1)>::first_argument_type b = 1; // error C2039: 'result_type': is not a member of 'bar::<lambda_227a80eb4d5d25e23ac8db99e4a9edf0>
    boost::binary_traits<decltype(func2)>::first_argument_type c = 1; // OK
    boost::binary_traits<std::function<int(int, int)>>::first_argument_type d = 1; // OK
}

How can I write foo so that the foo(func1) call works?

For context, this is what I'm trying to accomplish. Ideally without putting a bunch of helper templates alongside it in the header so that they're visible to the caller.

template<typename Iterable, typename Functor>
inline auto accumulate(Iterable& input, Functor&& accumulator)
{
    boost::binary_traits<Functor>::first_argument_type output;
    std::for_each(
        std::begin(input),
        std::end(input),
        [&output, &accumulator](auto& m) { output = accumulator(output, m); });
    return output;
}

I'm trying to use boost::binary_traits to get the type of a functor's argument. It works for std::function but not for "lambda types".

#include <boost/functional.hpp>

template<typename Functor>
void foo(Functor&& f)
{
    boost::binary_traits<Functor>::first_argument_type a = 1; // error C2528: 'abstract declarator': pointer to reference is illegal
}

void bar()
{
    auto func1 = [](int i, int j) { return j; };
    std::function<int(int, int)> func2 = [](int i, int j) { return j; };
    foo(func1);
    boost::binary_traits<decltype(func1)>::first_argument_type b = 1; // error C2039: 'result_type': is not a member of 'bar::<lambda_227a80eb4d5d25e23ac8db99e4a9edf0>
    boost::binary_traits<decltype(func2)>::first_argument_type c = 1; // OK
    boost::binary_traits<std::function<int(int, int)>>::first_argument_type d = 1; // OK
}

How can I write foo so that the foo(func1) call works?

For context, this is what I'm trying to accomplish. Ideally without putting a bunch of helper templates alongside it in the header so that they're visible to the caller.

template<typename Iterable, typename Functor>
inline auto accumulate(Iterable& input, Functor&& accumulator)
{
    boost::binary_traits<Functor>::first_argument_type output;
    std::for_each(
        std::begin(input),
        std::end(input),
        [&output, &accumulator](auto& m) { output = accumulator(output, m); });
    return output;
}
Share Improve this question asked Mar 19 at 18:34 H.v.M.H.v.M. 1,7093 gold badges20 silver badges45 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

According to the boost docs:

binary_traits should be instantiated with either a function taking two parameters, or an adaptable binary function object (i.e., a class derived from std::binary_function or one which provides the same typedefs). (See §20.3.1 in the C++ Standard.

A lambda doesn't meet either of those criteria, so it is not surprising that it doesn't work as-is. You will likely need to change your function to take a std::function (or applying a concept to enforce the boost::binary_traits requirements) instead of an arbitrary callable.

You could also use the deduction guides for std::function to your advantage:

template<typename Functor>
void foo(Functor&& f)
{
    typename decltype(std::function(f))::first_argument_type a = 1;
}
发布评论

评论列表(0)

  1. 暂无评论