如何创建一个在C++中接受Lambda表达式的辅助函数

huangapple go评论69阅读模式
英文:

How to Make a helper function which accepts a lambda in C++

问题

以下是您要求的代码部分的翻译:

现在我有一个函数,它对一个 uchar 数组进行一些更改(将充当查找表),以便我可以决定在该查找表上实现哪种转换。

for (size_t i = 0; i <= 255; ++i)
{
    lut_transform[0].at<uchar>(i) = 255 - i; //反转函数
}
for (size_t i = 0; i <= 255; ++i)
{
    lut_transform[1].at<uchar>(i) = pow((float)i * 255, (1/2.0)); //平方根函数
}
for (size_t i = 0; i <= 255; ++i)
{
    lut_transform[2].at<uchar>(i) = pow((float)i, 3.0) / (255*255); //立方函数
}

所以我想改进这个,并创建一个辅助函数,该函数接收数组和要实现的函数算法作为参数。应该看起来像这样。

void transform_function_helper(std::vector<uchar>& vec_tf, lambda_arg f(int)){
  for (int i = 0; i < vec_tf.size(); ++i) {
    vec_tf.at<uchar>(i) = f(i);
  }
}
void current_function_already_working(){
  /* 代码 */
  // 用辅助函数的调用替换三个 for 循环
  // lut_transform 是一个 uchar 向量的向量
  transform_function_helper(lut_transform[0], [](const int x) -> uchar { return 255 - x; } );
  transform_function_helper(lut_transform[1], [](const int x) -> uchar { return pow((float)x * 255, (1/2.0)); } );
  transform_function_helper(lut_transform[2], [](const int x) -> uchar { return pow((float)x, 3.0) / (255*255); } );
  /* 代码 */
}

如果您需要进一步的帮助,请随时告诉我。

英文:

Right now I have a function which makes some changes in an array of uchar (will act as a LUT) so I can decide which transformation will be implemented on that LUT.

for (size_t i = 0; i &lt;= 255; ++i)
{
    lut_transform[0].at&lt;uchar&gt;(i) = 255-i; //Inverse function
}
for (size_t i = 0; i &lt;= 255; ++i)
{
    lut_transform[1].at&lt;uchar&gt;(i) = pow((float)i * 255,(1/2.0)); //Square Root function
}
for (size_t i = 0; i &lt;= 255; ++i)
{
    lut_transform[2].at&lt;uchar&gt;(i) = pow((float)i, 3.0) / (255*255); //Cubic function
}

So I want to improve this and create a helper function which receives as a parameter the array and the function algorithm to implement. So should look something like this.

void transform_function_helper (std::vector&lt;uchar&gt;&amp; vec_tf, lambda_arg f(int)){
  for (int i = 0; i &lt; vec_tf.size(); ++i) {
    vec_tf.at&lt;uchar&gt;(i) = f(i);
  }
}
void current_function_already_working(){
  /* code */
  //replacing the 3 for for the calls to the helper function
  //lut_transform is a vector of uchar vector
  transform_function_helper(lut_transform[0], [](const int x) -&gt; uchar { 255 - x; } );
  transform_function_helper(lut_transform[1], [](const int x) -&gt; uchar { pow((float)x * 255,(1/2.0)); } );
  transform_function_helper(lut_transform[2], [](const int x) -&gt; uchar { pow((float)x, 3.0) / (255*255); } );
  /*code*/
}

I hope this is clear.

答案1

得分: 3

以下是代码的中文翻译部分:

你有三种选择:

  1. 使用纯C风格的函数指针(因为你没有使用任何捕获lambda表达式),例如:
void transform_function_helper(std::vector<uchar>& vec_tf, uchar (*f)(size_t)) {
  for (size_t i = 0; i < vec_tf.size(); ++i) {
    vec_tf[i] = f(i);
  }

  /* 或者:
  size_t i = 0;
  for (auto &elem : vec_tf) {
    elem = f(i++);
  }
  */
}
  1. 使用std::function,例如:
#include <functional>

void transform_function_helper(std::vector<uchar>& vec_tf, std::function<uchar(size_t)> f) {
  for (size_t i = 0; i < vec_tf.size(); ++i) {
    vec_tf[i] = f(i);
  }

  /* 或者:
  size_t i = 0;
  for (auto &elem : vec_tf) {
    elem = f(i++);
  }
  */
}
  1. 使用模板函数,例如:
template<typename Callable>
void transform_function_helper(std::vector<uchar>& vec_tf, Callable f) {
  for (size_t i = 0; i < vec_tf.size(); ++i) {
    vec_tf[i] = f(i);
  }

  /* 或者:
  size_t i = 0;
  for (auto &elem : vec_tf) {
    elem = f(i++);
  }
  */
}

无论哪种方式,然后你可以像这样调用辅助函数:

void current_function_already_working(){
  /* 代码 */
  // 用辅助函数替代3个循环
  // lut_transform是一个uchar向量的向量
  transform_function_helper(lut_transform[0], [](size_t x) -> uchar { return 255 - x; } );
  transform_function_helper(lut_transform[1], [](size_t x) -> uchar { return pow((float)x * 255, (1/2.0)); } );
  transform_function_helper(lut_transform[2], [](size_t x) -> uchar { return pow((float)x, 3.0) / (255*255); } );
  /* 代码 */
}
英文:

You have three choices:

  1. use a plain C-style function pointer (since you are not using any capturing lambdas), eg:
void transform_function_helper (std::vector&lt;uchar&gt;&amp; vec_tf, uchar (*f)(size_t)) {
  for (size_t i = 0; i &lt; vec_tf.size(); ++i) {
    vec_tf[i] = f(i);
  }

  /* alternatively:
  size_t i = 0;
  for (auto &amp;elem : vec_tf) {
    elem = f(i++);
  }
  */
}
  1. Use std::function, eg:
#include &lt;functional&gt;

void transform_function_helper (std::vector&lt;uchar&gt;&amp; vec_tf, std::function&lt;uchar(size_t)&gt; f) {
  for (size_t i = 0; i &lt; vec_tf.size(); ++i) {
    vec_tf[i] = f(i);
  }

  /* alternatively:
  size_t i = 0;
  for (auto &amp;elem : vec_tf) {
    elem = f(i++);
  }
  */
}
  1. Use a template function, eg:
template&lt;typename Callable&gt;
void transform_function_helper (std::vector&lt;uchar&gt;&amp; vec_tf, Callable f) {
  for (size_t i = 0; i &lt; vec_tf.size(); ++i) {
    vec_tf[i] = f(i);
  }

  /* alternatively:
  size_t i = 0;
  for (auto &amp;elem : vec_tf) {
    elem = f(i++);
  }
  */
}

Either way, you can then call the helper function like this:

void current_function_already_working(){
  /* code */
  //replacing the 3 for for the calls to the helper function
  //lut_transform is a vector of uchar vector
  transform_function_helper(lut_transform[0], [](size_t x) -&gt; uchar { return 255 - x; } );
  transform_function_helper(lut_transform[1], [](size_t x) -&gt; uchar { return pow((float)x * 255,(1/2.0)); } );
  transform_function_helper(lut_transform[2], [](size_t x) -&gt; uchar { return pow((float)x, 3.0) / (255*255); } );
  /*code*/
}

答案2

得分: 0

这就是 std::transform 的作用。如果您使用 C++20 或更新的版本,您可以使用 std::ranges::transform

#include <algorithm>
#include <cmath>
#include <vector>

int main(){
    using uchar = unsigned char;

    std::vector<uchar> data{3, 5, 8};

    std::ranges::transform(data, data.begin(),
        [](const uchar x) {
            return static_cast<uchar>(255 - x);
        });

    std::ranges::transform(data, data.begin(),
        [](const uchar x) {
            return static_cast<uchar>(std::pow(x * 255, 0.5));
        });

    std::ranges::transform(data, data.begin(),
        [](const uchar x) {
            return static_cast<uchar>(std::pow(x, 3.0) / (255 * 255));
        });
}

请注意,如果使用整数参数,std::pow 会自动转换为 double 类型。此外,请注意,我已将 lambda 表达式的参数类型更改为 uchar,这是向量的实际类型。在 lambda 表达式中的显式 static_cast 更好,因为它可以抑制隐式转换警告。

在 C++20 之前(C++11)的代码如下:

#include <algorithm>
#include <cmath>
#include <vector>

int main(){
    using uchar = unsigned char;

    std::vector<uchar> data{3, 5, 8};

    std::transform(data.cbegin(), data.cend(), data.begin(),
        [](const uchar x) {
            return static_cast<uchar>(255 - x);
        });

    std.transform(data.cbegin(), data.cend(), data.begin(),
        [](const uchar x) {
            return static_cast<uchar>(std::pow(x * 255, 0.5));
        });

    std.transform(data.cbegin(), data.cend(), data.begin(),
        [](const uchar x) {
            return static_cast<uchar>(std::pow(x, 3.0) / (255 * 255));
        });
}
英文:

This is what std::transform does. If you use C++20 or newer, you can use std::ranges::transform:

#include &lt;algorithm&gt;
#include &lt;cmath&gt;
#include &lt;vector&gt;

int main(){
    using uchar = unsigned char;

    std::vector&lt;uchar&gt; data{3, 5, 8};

    std::ranges::transform(data, data.begin(),
        [](const uchar x) {
            return static_cast&lt;uchar&gt;(255 - x);
        });

    std::ranges::transform(data, data.begin(),
        [](const uchar x) {
            return static_cast&lt;uchar&gt;(std::pow(x * 255, 0.5));
        });

    std::ranges::transform(data, data.begin(),
        [](const uchar x) {
            return static_cast&lt;uchar&gt;(std::pow(x, 3.0) / (255 * 255));
        });
}

Note that std::pow automatically casts to double if use use integer arguments. Also note that I replaced the lambdas parameter type to uchar which is the vectors actual type. The explicit static_cast in the lambdas is better then explicit return type notation, because it suppresses implicit conversion warnings.

The pre C++20 (C++11) code would be:

#include &lt;algorithm&gt;
#include &lt;cmath&gt;
#include &lt;vector&gt;

int main(){
    using uchar = unsigned char;

    std::vector&lt;uchar&gt; data{3, 5, 8};

    std::transform(data.cbegin(), data.cend(), data.begin(),
        [](const uchar x) {
            return static_cast&lt;uchar&gt;(255 - x);
        });

    std::transform(data.cbegin(), data.cend(), data.begin(),
        [](const uchar x) {
            return static_cast&lt;uchar&gt;(std::pow(x * 255, 0.5));
        });

    std::transform(data.cbegin(), data.cend(), data.begin(),
        [](const uchar x) {
            return static_cast&lt;uchar&gt;(std::pow(x, 3.0) / (255 * 255));
        });
}

huangapple
  • 本文由 发表于 2023年3月7日 08:14:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75656964.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定