No matching function error when passing lambda function as argument

前端 未结 1 1239
误落风尘
误落风尘 2021-01-05 00:36

I have a list of numbers.

I am trying to filter the list and only keep the positive numbers.

I am trying to do it by passing a lambda as an argument.

1条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2021-01-05 00:49

    Change the function keep to

    template
    std::vector keep(const std::vector &original,
                        Func useful)
    {
        // code as usual
    }
    

    Live example.

    This works with an argument to useful being any one of these:

    • lambda
    • std::function
    • functor
    • function pointer

    From the documentation:

    The lambda expression constructs an unnamed prvalue temporary object of unique unnamed non-union non-aggregate type, known as closure type.

    This means that two lambdas with the same code, would generate two different typed objects.

    auto f1 = [](int) { return true; };
    auto f2 = [](int) { return false; };
    f2 = f1;                               // error: no viable '='
    

    However, both of these are implicitly convert-able to the corresponding std::function types:

    std::function fn = f1;
    fn = f2;
    

    But then why doesn't it work in your case? This is because of template type deduction. Changing keep to

    template
    std::vector keep(const std::vector &original,
                        std::function useful)
    // no type deduction for std::function's template, explicitly mentioned
    

    will make your example compile without any cast at the caller site.

    However, trying to match it against std::function won't work since template type deduction doesn't consider any conversion. Template argument deduction looks for exact type matches. Implicit conversions don't matter at this stage. You've to explicitly cast it to a matching std::function as Atomic_alarm comments. Like Joseph says in How to convert a lambda to an std::function using templates:

    Template type deduction tries to match the type of your lambda function to the std::function which it just can't do in this case - these types are not the same. Template type deduction doesn't consider conversions between types.

    While in the alternative solution what happens is something like this:

    auto f = [](int i) { return (i >= 0); }
    

    The type of f here is not std::function but some unnamed type deduced like it would for the template parameter Func above.

    If you still want to do it the std::function way, see this answer which does it with an additional template indirection. See this answer and this post for related details.

    0 讨论(0)
提交回复
热议问题