Как использовать лямбду, возвращающую bool, в качестве параметра - PullRequest
0 голосов
/ 24 мая 2019

Я пытаюсь передать лямбду в качестве параметра функции, которая указывает, должны ли элементы быть включены в новый вектор.

В настоящее время я использую шаблоны для типа вектора (T) и лямбдывыражение (Func).Но как я могу заставить функцию принимать лямбду с T в качестве параметра и bool в качестве возвращаемого типа?

Это мой актуальный код:

#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 ]

2 голосов
/ 24 мая 2019

В общем, мы стараемся избегать создания шаблонов, требующих определенной подписи.

Мы предпочитаем:

  • требования к документу и
  • полагаться на ошибки компилятора, когда что-то не так.

Как таковой, ваш шаблон функции выглядит хорошо, а ваше использование выглядит хорошо, и поэтому все работает.

Конечно, вы могли бы передать что-то, что не ... 1013 *, что независимо работало в операторе if. И вы могли бы передать что-то, что не ... 1015 *, но все равно работало & hellip; но тогда и что? Просто не делай таких вещей. Если он ходит как утка -

С некоторыми механизмами возможно гарантировать, что вызываемый объект принимает конкретные аргументы и возвращает значение определенного типа, но это было бы сложно и откровенно бесполезно.

Короче, ваш код в порядке .

1 голос
/ 24 мая 2019

Вы можете написать свой шаблон так:

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 демо


Редактировать: Если вы когда-нибудь захотите передать не захватывающую лямбду, вам будет немного удобнее определить ваш шаблон следующим образом:

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

Но вы все равноМне нужно «дополнительное оборудование» на сайте вызова, на которое ссылаются гонки на легкость на орбите (я думаю, что вычитание шаблона не удастся, потому что количество параметров шаблона больше не соответствует количеству параметров, переданных Where).

Live демо

В общем, придерживайтесь своего исходного кода.

0 голосов
/ 24 мая 2019

Попробуйте изменить подпись шаблона 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...