【问题标题】:"Capture" variables in lambda function parsed as argumentlambda 函数中的“捕获”变量解析为参数
【发布时间】:2017-09-21 05:51:41
【问题描述】:

对不起,我不知道该如何命名这个问题。


我在 C++ 中有一个函数,它接受一个 lambda 作为参数。

void LoopPixels(cv::Mat &img, void(*fptr)(uchar &r, uchar &g, uchar &b)) {
    // ...
    fptr(r, g, b); // Call the lambda function
}

然后我尝试调用这个LoopPixels 函数。

int threshold = 50;
LoopPixels(img, [](uchar &r, uchar &g, uchar &b) {
    r *= (uchar)threshold; // Unable to access threshold :(
});

我的问题是,我无法从 lambda 函数内部访问 threshold 变量,如果我尝试使用 [&threshold](uchar &r...){} "catch" 它,我会收到一条错误消息,告诉我 lambda我解析成LoopPixels 是错误的类型。

错误信息:

没有合适的转换函数来自“lambda []void (uchar &r, uchar &g, uchar &b)->void" 到 "void (*)(uchar &r, uchar &g, uchar &b)" 存在

如何访问已被解析为函数参数的 lambda 中的变量?

【问题讨论】:

  • 只有不捕获任何内容的 lambda 才能转换为函数指针。将您的函数更改为模板,并将函数指针更改为模板参数。
  • 好的,我已将我的函数更改为template <class T> void LoopPixels(cv::Mat &img, T *fptr),我得到Couldn't match type 'T*' against <lambda>
  • 你传递一个 lambda,而不是一个指针。因此出现错误消息。
  • “将 lambda 作为参数。”。不,您的函数采用函数指针(并且无捕获 lambda 可以转换为该指针)。

标签: c++ c++11 lambda


【解决方案1】:

您不能将捕获 lambda 传递给函数指针。您必须更改函数以使用std::function,或使用函数模板。

void LoopPixels1(cv::Mat &img, std::function<void(uchar &r, uchar &g, uchar &b)> fn);
// Or:
template<typename Callable>
void LoopPixels2(cv::Mat &img, Callable fn);

// Can be called with a capturing lambda
LoopPixels1(img, [threshold](uchar &r, uchar &g, uchar &b) { });
LoopPixels2(img, [threshold](uchar &r, uchar &g, uchar &b) { });

【讨论】:

  • 您能否举例说明我如何致电LoopPixels
  • 值得一提:使用第一个选项,不要忘记包含标题&lt;functional&gt;
【解决方案2】:

你可以试试这个:

void LoopPixels(cv::Mat& img, uint& r, uint& g, uint& b, const std::function<void(uint& r, uint& g, uint& b)>& callback)
{
    callback(r, g, b);
}

cv::Mat img;
int threshold = 50;
uint r = 1;
uint g = 1;
uint b = 1;

std::cout << "(before) rgb : " << r << g << b << std::endl;

LoopPixels(img, r, g, b, [threshold](uint& r, uint& g, uint& b)
{
   r *= threshold;
   g *= threshold;
   b *= threshold;
});

std::cout << "(after) rgb : " << r << g << b << std::endl;

lamba 捕获是按值传递的,因为引用可能在回调调用之前超出范围。

(我将 uint 用于 r、g、b 变量而不是 uchar,因为将 uchar 与 int 相乘可能不会得到您期望的结果)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 2021-02-07
    • 1970-01-01
    相关资源
    最近更新 更多