从 lambda 表达式返回布尔值时出错

Error while returning boolean from lambda expressions

本文关键字:出错 布尔值 返回 lambda 表达式      更新时间:2023-10-16
bool markersFormRectangle = [](std::vector<cv::Point2f> markerCoords) {
cv::Point2f center(
(markerCoords[0].x + markerCoords[1].x + markerCoords[2].x + markerCoords[3].x) / 4,
(markerCoords[0].y + markerCoords[1].y + markerCoords[2].y + markerCoords[3].y) / 4
);
float dd1 = cv::norm(center - markerCoords[0]);
float dd2 = cv::norm(center - markerCoords[1]);
float dd3 = cv::norm(center - markerCoords[2]);
float dd4 = cv::norm(center - markerCoords[3]);
return (fabs(dd1-dd2) < 5) && (fabs(dd1 - dd3) < 5) && (fabs(dd1 - dd4) < 5);
};

我正在尝试使用上述 lambda 表达式来检查四个点是否形成近矩形。但是编译器抱怨错误:当我尝试通过以下方式在 if 语句中使用 lambda 表达式时,调用的对象类型 'bool' 不是函数或函数指针

if (markersFormRectangle(markerPoints)) {
//do something
}

当我更改返回类型auto时,它不会给我该错误。我对使用 lambda 函子很陌生。你能告诉我我做错了什么,以及为什么如果类型更改为auto编译器不再给出错误?

在此声明中

bool markersFormRectangle = [](std::vector<cv::Point2f> markerCoords)
{
cv::Point2f center((markerCoords[0].x +markerCoords[1].x + markerCoords[2].x + markerCoords[3].x) / 4,
(markerCoords[0].y +markerCoords[1].y + markerCoords[2].y + markerCoords[3].y) / 4);
float dd1 = cv::norm(center - markerCoords[0]);
float dd2 = cv::norm(center - markerCoords[1]);
float dd3 = cv::norm(center - markerCoords[2]);
float dd4 = cv::norm(center - markerCoords[3]);
return (fabs(dd1-dd2) < 5) && (fabs(dd1 - dd3) < 5) && (fabs(dd1 - dd4) < 5);
};

初始值设定项是一个 lambda 表达式,而声明的变量具有 bool 类型。没有从 lambda 表达式类型到类型bool的隐式或上下文相关转换。

考虑到每个 lambda 都有自己独特的类型。

所以你必须写

auto markersFormRectangle = [](std::vector<cv::Point2f> markerCoords)
{
cv::Point2f center((markerCoords[0].x +markerCoords[1].x + markerCoords[2].x + markerCoords[3].x) / 4,
(markerCoords[0].y +markerCoords[1].y + markerCoords[2].y + markerCoords[3].y) / 4);
float dd1 = cv::norm(center - markerCoords[0]);
float dd2 = cv::norm(center - markerCoords[1]);
float dd3 = cv::norm(center - markerCoords[2]);
float dd4 = cv::norm(center - markerCoords[3]);
return (fabs(dd1-dd2) < 5) && (fabs(dd1 - dd3) < 5) && (fabs(dd1 - dd4) < 5);
};

来自 C++14 标准(5.1.2 Lambda 表达式)

3 lambda 表达式的类型(这也是 闭包对象)是一个唯一的、未命名的非联合类类型,称为 闭包类型 — 其属性如下所述。此类类型 既不是聚合 (8.5.1) 也不是文本类型 (3.9)。

要显式指定 lambda 返回类型,您可以使用尾随返回类型说明符编写

auto markersFormRectangle = [](std::vector<cv::Point2f> markerCoords) -> bool
{
cv::Point2f center((markerCoords[0].x +markerCoords[1].x + markerCoords[2].x + markerCoords[3].x) / 4,
(markerCoords[0].y +markerCoords[1].y + markerCoords[2].y + markerCoords[3].y) / 4);
float dd1 = cv::norm(center - markerCoords[0]);
float dd2 = cv::norm(center - markerCoords[1]);
float dd3 = cv::norm(center - markerCoords[2]);
float dd4 = cv::norm(center - markerCoords[3]);
return (fabs(dd1-dd2) < 5) && (fabs(dd1 - dd3) < 5) && (fabs(dd1 - dd4) < 5);
};

虽然没有必要。

请记住(5.1.2 Lambda 表达式)

7 lambda表达式的复合语句产生函数体 (8.4)的函数调用运算符,...

Lambda 只能存储在auto类型的变量中或转换为函数指针(例如使用std::function),如果你想得到你的 lambda 的结果,你需要称之为 fist。您的代码应为:

auto markers = []{ return true; };
bool value = markers();

bool value = []{ return true; }();

取决于您是尝试存储 lambda 还是其结果。