如何使用lambda返回布尔值作为参数

时间:2019-05-23 22:50:04

标签: c++ lambda

我试图将lambda作为参数传递给一个函数,该函数指定是否应在新向量中包含项目。

目前,我正在使用矢量类型(T)和lambda表达式(Func)的模板。但是,如何使该函数接受以T为参数,以bool为返回类型的lambda?

这是我的实际代码:

#include <string>
#include <vector>

using namespace std;

// DTO with some members
struct DTO
{
    int Id;
    string Name;
    string Note;
};

// Function to receive a new vector, containing the searched items
template<typename T, typename Func>
vector<T> Where(vector<T> input, Func lambda)
{
    vector<T> v;
    for (auto it = input.begin(); it != input.end(); ++it)
        if (lambda(*it))
            v.push_back(*it);
    return v;
}

int main()
{
// Some test data
    DTO dto1;
    dto1.Id = 1;
    dto1.Name = "Test";
    dto1.Note = "asdasfa";
    DTO dto2;
    dto2.Id = 2;
    dto2.Name = "Test";
    dto2.Note = "asdasfa";
    DTO dto3;
    dto3.Id = 2;
    dto3.Name = "Test2";
    dto3.Note = "asdasfa";
    DTO dto4;
    dto4.Id = 2;
    dto4.Name = "Test2";
    dto4.Note = "asdasfa";
    DTO dto5;
    dto5.Id = 2;
    dto5.Name = "Test2";
    dto5.Note = "123";

    vector<DTO> numbers2 = 
    { 
        dto1,dto2,dto3,dto4,dto5
    };
// Get new vector with items where Name is Test and Note is asdasfa
    auto test = Where(numbers2, [](DTO dto) 
    {
        return dto.Name == "Test" &&
            dto.Note == "asdasfa";
    });
}

目标是使函数调用者感到最舒适。

3 个答案:

答案 0 :(得分:1)

通常,我们试图避免使模板必须具有特定的签名。

我们更愿意:

  • 文档要求,和
  • 在某些不正确的地方依靠编译器错误。

实际上,您的功能模板看起来不错,用法也很不错,这就是一切正常的原因。

当然,您可以传递不返回的内容-bool,无论该内容在if语句中是否起作用。而且您可以传递不花钱的东西-DTO但仍然可以工作……但是那又如何呢?只是不要做那些事。如果它走路像鸭子一样……

有可能使用某些机制来确保可调用对象采用特定的参数并返回特定类型的值,但这很复杂并且坦率地说没有用。

简而言之,您的代码很好

答案 1 :(得分:0)

尝试将Where的模板签名更改为SFINAE,以使用不需要的Func类型:

template<typename T,
         typename Func,
         std::enable_if_t<std::is_same_v<bool, std::invoke_result_t<Func, T>>>* = nullptr>
vector<T> Where(vector<T> input, Func lambda)

答案 2 :(得分:0)

您可以这样编写模板:

template<typename T>
std::vector<T> Where(std::vector<T> input, std::function <bool (T)> f)
{
    std::vector<T> v;
    for (auto it = input.begin(); it != input.end(); ++it)
        if (f(*it))
            v.push_back(*it);
    return v;
}

但是您必须这样调用它:

auto test = Where <DTO> (numbers2, [](DTO dto) 
{
    ...
});

Live demo


编辑:如果您只想传递不捕获的lambda,则这样定义模板的效率会更高:

template<typename T>
std::vector<T> Where(std::vector<T> input, bool (* f) (T))
...

但是您仍然需要Lightness Race in Orbit所指的呼叫站点上的“额外设备”(我认为模板推导失败,因为模板参数的数量不再与传递给Where的参数数量匹配)

Live demo

全部,坚持原始代码。