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

时间:2018-04-13 13:18:38

标签: c++ lambda boolean

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表达式来检查这四个点是否形成近似矩形的形状。但编译器抱怨错误:称为对象类型&#39; bool&#39;当我尝试以下列方式在if语句中使用lambda表达式时,它不是函数或函数指针

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

当我更改返回类型auto时,它不会给我这个错误。我很擅长使用lambda仿函数。你能否告诉我我做错了什么以及如果类型改为auto,编译器为什么不再给出错误?

2 个答案:

答案 0 :(得分:5)

在此声明中

        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表达式的类型(也是表达式的类型)   closure object)是一个唯一的,未命名的nonunion类类型 - 称为   闭包类型 - 其属性如下所述。这个类类型   既不是聚合(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-expression的复合语句产生函数体   (8.4)函数调用运算符,...

答案 1 :(得分:3)

Lambdas只能存储在auto类型的变量中,或者转换为函数指针(例如使用std::function),如果你想获得lambda的结果,你需要将其称为拳头。您的代码应该是:

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

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

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