简体   繁体   English

如何正确使用std :: function作为谓词

[英]How to properly use std::function as a predicate

I want to use std::function as a predicate in a templated helper function but I get an error: 我想将std :: function用作模板化辅助函数中的谓词,但出现错误:

 main.cpp(15): error C2672: 'Any': no matching overloaded function found main.cpp(15): error C2784: 'bool Any(const std::vector<T,std::allocator<_Ty>> &,const std::function<bool(const T &)>)': could not deduce template argument for 'const std::function<bool(const T &)>' from 'main::<lambda_1b47ff228a1af9c86629c77c82b319f9>' main.cpp(7): note: see declaration of 'Any' 
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

template <typename T>
bool Any(const std::vector<T>& list, const std::function<bool(const T&)> predicate)
{   
    return std::any_of(list.begin(), list.end(), [&](const T& t) { return predicate(t); });
}

int main()
{
    auto myList = std::vector<int>{ 1, 2, 3, 4, 5 };
    if (Any(myList, [](int i) { return i % 5 == 0; }))
    {
        std::cout << "Bingo!" << std::endl;
    }
    else
    {
        std::cout << "Not found :(" << std::endl;
    }

    return 0;
}

I don't understand what I'm doing wrong. 我不明白我在做什么错。

I don't understand what I'm doing wrong. 我不明白我在做什么错。

You're passing a lambda to Any , but the implicit conversion (from lambda to std::function ) won't be considered in template argument deduction , which makes T can't be deduced on the 2nd function argument. 您正在将lambda传递给Any ,但是模板参数deduction不会考虑隐式转换(从lambda到std::function ),这使得无法在第二个函数参数上推导T

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution , which happens later. 类型推导不考虑隐式转换(上面列出的类型调整除外):这是超载解析的工作,稍后会发生。

You can use std::type_identity (since C++20) to exclude the 2nd argument from deduction; 您可以使用std::type_identity (C ++ 20起)从推论中排除第二个参数; then the template parameter T would be deduced on only the 1st argument, then the code works fine. 然后仅在第一个参数上推导出模板参数T ,然后代码可以正常工作。 eg 例如

template <typename T>
bool Any(const std::vector<T>& list, const std::function<bool(const std::type_identity_t<T>&)> predicate)
//                                                                  ^^^^^^^^^^^^^^^^^^^^^^^
{   
    return std::any_of(list.begin(), list.end(), [&](const T& t) { return predicate(t); });
}

LIVE 生活

If you can't apply C++20, you can refer to the linked page above which gives a possible implementation, it's not hard to implement your own type_identity . 如果您不能应用C ++ 20,则可以参考上面的链接页面,该页面提供了可能的实现,实现您自己的type_identity并不难。 If you don't stick to std::function , you can just add another template parameter for predicate. 如果您不坚持使用std::function ,则可以为谓词添加另一个模板参数。

template <typename T, typename P>
bool Any(const std::vector<T>& list, P predicate)
{   
    return std::any_of(list.begin(), list.end(), predicate);
}

LIVE 生活

Or make it more general to work with other containers or raw arrays. 或者使它与其他容器或原始数组一起使用更为通用。

template <typename C, typename P>
bool Any(const C& c, P predicate)
{   
    return std::any_of(std::begin(c), std::end(c), predicate);
}

LIVE 生活

Correct Code: 正确的代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

template <typename T>
bool Any(const std::vector<T>& list, const std::function<bool(const T&)> predicate)
{   
    return std::any_of(list.begin(), list.end(), [&](const T& t) { return predicate(t); });
}

int main()
{
    auto myList = std::vector<int>{ 1, 2, 3, 4, 5 };
    if (Any<int>(myList, [](int i) -> bool { return i % 5 == 0; }))
    {
        std::cout << "Bingo!" << std::endl;
    }
    else
    {
        std::cout << "Not found :(" << std::endl;
    }

    return 0;
}

if (Any<int>(myList, [](int i) -> bool { return i % 5 == 0; }))

  1. You need to specify template argument (Any) 您需要指定模板参数(任意)
  2. You forgot to add return type of lambda 您忘记添加lambda的返回类型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM