Тема: Конвертувати лямбда у вказівник на функцію
Задача:
Маю клас, екземпляри якого містять дані в своїх полях (поля різного типу). Всі екземпляри мають однакову структуру. Маю масив (вказівник на масив і розмір масиву) таких екземплярів. Хочу зробити функцію, яка буде: в масиві шукати елемент за вказаними значеннями полів екземпляра, і вертати вказівник на знайдений елемент (або nullptr якщо такого елемента не знайдено).
Рішення:
Зробив функцію, яка приймає 3 параметри:
Вказівник на масив: SomeData const *
Розмір масиву: int
Вказівник на функцію, яка визначає чи відповідає елемент заданій умові: bool (*)(SomeData const &)
і сама вона компілюється без проблем.
Не очікувана проблема:
Помилки компіляції появляються, коли я викликаю цю функцію, де 3-тій параметр - lambda.
GetItemByMatch(arr, size, [id](SomeData const &data) -> bool { return data.id == id; });
GetItemByMatch(arr, size, [name](SomeData const &data) -> bool { return !strcmp(data.name, name); });
Коди помилок: C2664, E0413.
Error C2664
'const SomeData *GetItemByMatch(const SomeData *const, const int, bool (__cdecl *const )(const SomeData &))':
cannot convert argument 3
from 'GetItemByName::<lambda_xxxxxxxxxxx(hex-addr)xxxxxxxxxxx>'
to 'bool (__cdecl *const )(const SomeData &)'
Error (active) E0413
no suitable conversion function
from "lambda []bool (const SomeData &data)->bool"
to "bool (*)(const SomeData &)" exists
Мій код (3 файли, мінімальний приклад для відтворення проблеми):
// main.cpp
#include <iostream>
#include "SomeData.hpp"
int main(int const argc, char const *const argv[]) {
int const size = 3;
SomeData *arr = new SomeData[size]{
SomeData(0, "Some name"),
SomeData(1, "Other name"),
SomeData(2, "Another name")
};
int id = 1;
SomeData const *ptr = GetItemById(arr, size, id);
if(ptr) {
std::cout << *ptr;
ptr = nullptr;
}
else
std::cout << "Item with id " << id << " was not found.";
delete[] arr;
return 0;
}
// SomeData.hpp
#ifndef _SOMEDATA_HPP_
#define _SOMEDATA_HPP_
#include <iostream>
class SomeData {
private:
int id;
char const *name;
// та інші поля ...
public:
SomeData(int id, char const *name);
friend std::ostream &operator <<(std::ostream &out, SomeData const &data);
friend SomeData const *GetItemById(SomeData const *const arr, int const size, int const id);
friend SomeData const *GetItemByName(SomeData const *const arr, int const size, char const *const name);
};
std::ostream &operator <<(std::ostream &out, SomeData const &data);
SomeData const *GetItemById(SomeData const *const arr, int const size, int const id);
SomeData const *GetItemByName(SomeData const *const arr, int const size, char const *const name);
SomeData const *GetItemByMatch(SomeData const *const arr, int const size, bool (*const match)(SomeData const &));
#endif
// SomeData.cpp
#include <iostream>
#include <string.h>
#include "SomeData.hpp"
SomeData::SomeData(int id, char const *name) : id(id), name(name) {}
std::ostream &operator <<(std::ostream &out, SomeData const &data) {
return out
<< "Id: " << data.id << ", "
<< "Name: \"" << data.name << "\", "
// та інші поля ...
<< "...";
}
SomeData const *GetItemById(SomeData const *const arr, int const size, int const id) {
return GetItemByMatch(arr, size, [id](SomeData const &data) -> bool { return data.id == id; });
}
SomeData const *GetItemByName(SomeData const *const arr, int const size, char const *const name) {
return GetItemByMatch(arr, size, [name](SomeData const &data) -> bool { return !strcmp(data.name, name); });
}
SomeData const *GetItemByMatch(SomeData const *const arr, int const size, bool (*const match)(SomeData const &)) {
if(!arr || !match)
return nullptr;
for(int i = 0; i < size; ++i)
if(match(arr[i]))
return arr + i;
return nullptr;
}
Питання:
Як передавати критерії пошуку (лямбда вирази) у функцію ?