如何避免使用已知函数参数的 lambda 函数?

How to avoid lambda functions with a known function parameter?

在下面的代码中,我有一个名为 data 的变量。它在自身内部包含一个函数,以便稍后调用它们。假设 data 是在另一个库中定义的,我无法更改它的类型。我为它的每个成员分配一个模板函数,其中该函数的一部分是已知的 (s3),并且在调用它时必须给出一部分 (true)。我不能通过这样的东西:

data[0]=test_func(?,s3);  // error

相反,我必须向它传递一个 lambda 函数:

data[0]=[](bool b){test_func(b,s3);}; // ok

但是 lambda 函数看起来并不整洁,尤其是当我们有一个包含 100 个这样的赋值的数组时。有没有办法通过以任何方式更改 test_func 来避免 lambda 函数?即使在 test_func 中使用 lambda 对我来说也可以,因为它只写了一次。

#include <iostream>
#include <functional>

template<typename F>
void test_func(bool b,F f)
{
    if(b)
        f();
}

void s1()
{
    std::cout<<"s1 \n";
}

void s2()
{
    std::cout<<"s2 \n";
}

void s3()
{
    std::cout<<"s3 \n";
}

int main()
{
    test_func(true,s1);
    test_func(true,s2);
    test_func(false,s1);
    test_func(true,s2);
    /////////////////
    std::function<void(bool)> data[100];
    // data=test_func(?,s3);  // error
    data[0]=[](bool b){test_func(b,s3);}; // ok
    data[0](true);
    return 0;
}

如果您想像 templates 一样完全避免 lambda 函数,您可以使用函数式(class 和 operator()):

typedef void (&F)(void);
class TestFunc {
    F f;
    public:
    TestFunc(const F f) : f(f) {}
    void operator()(bool B) const { 
        if(B) f(); 
    }
};

TestFunc(s3)赋值。只需 typedef F 到函数类型,不需要模板:

typedef void (&F)(void);

并完全删除模板 - 如果可能的话,我通常更喜欢更少的模板,但这就是品味。只有当您需要不同的函数签名支持时,才会真正需要模板。

要使用标准库功能,只需更改 typedef:

typedef std::function<void(void)> F;

您可以在辅助函数中创建 lambda:

#include <iostream>
#include <string>
#include <functional>
#include <vector>

template<typename F>
void test_func(bool b,F f) {
    if(b) {
       f();
    }
}

std::function<void(bool)> wrap_function(const std::function<void(void)> &f) {
    return [f](bool b){test_func(b,f);};
}

void s1() {
    std::cout<<"s1 \n";
}

int main() {
    std::vector<std::function<void(bool)>> data;

    data.push_back(wrap_function(s1));

    data[0](true);
}

并且您应该使用 std::vectorstd::array 或其他标准容器而不是 std::function<void(bool)> data[100]

如果每个 s_n 都是具有相同签名的常规函数​​,您可以只从 test_func 中删除 f 参数,而是将函数本身作为模板参数传递。

template<void(&f)()>
void test_func(bool b)
{
    if(b)
        f();
}

并像这样使用:

data[0] = test_func<s1>;

[temp.param/4] 明确允许函数指针和引用作为模板非类型参数:

A non-type template-parameter shall have one of the following (optionally cv-qualified) types:

[...]

  • pointer to object or pointer to function,
  • lvalue reference to object or lvalue reference to function,