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

C++ 如何避免使用已知函数参数的lambda函数?,c++,c++11,templates,lambda,std-function,C++,C++11,Templates,Lambda,Std Function,在下面的代码中,我有一个名为data的变量。它在自身内部保存一个函数,以便稍后调用它们。假设数据是在另一个库中定义的,我无法更改其类型。我将一个模板函数分配给它的每个成员,其中该函数的一部分是已知的s3,当它被称为true时,必须给出一部分。我不能通过这样的考试: data[0]=test_func(?,s3); // error data[0] = test_func<s1>; 相反,我必须将lambda函数传递给它: data[0]=[](bool b){test_func

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

data[0]=test_func(?,s3);  // error
data[0] = test_func<s1>;
相反,我必须将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;
}
如果要完全避免使用lambda函数和模板,可以使用带运算符的函数类:

用TestFuncs3分配它。只需将DEF F键入函数类型,无需模板:

typedef void (&F)(void);
并完全删除模板-如果可能的话,我通常更喜欢少一些模板,但这就是味道。只有当您需要不同的函数签名支持时,才会真正调用模板

要使用标准库函数,只需更改typedef:

如果要完全避免使用lambda函数和模板,可以使用带运算符的函数类:

用TestFuncs3分配它。只需将DEF F键入函数类型,无需模板:

typedef void (&F)(void);
并完全删除模板-如果可能的话,我通常更喜欢少一些模板,但这就是味道。只有当您需要不同的函数签名支持时,才会真正调用模板

要使用标准库函数,只需更改typedef:


您可以在助手函数中创建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::vector、std::array或其他std容器代替std::function data[100]

您可以在助手函数中创建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::vector、std::array或其他std容器,而不是std::function data[100]

如果每个序列号都是具有相同签名的常规函数,您只需从test\u func中删除该f参数,并将函数本身作为模板参数传递

template<void(&f)()>
void test_func(bool b)
{
    if(b)
        f();
}
然后像这样使用:

data[0]=test_func(?,s3);  // error
data[0] = test_func<s1>;
函数指针和引用通过以下方式明确允许作为模板非类型参数:

非类型模板参数应具有以下之一: 可选cv限定类型:

[……]

指向对象的指针或指向函数的指针, 对对象的左值引用或对函数的左值引用, 如果每个s_n都是具有相同签名的正则函数,则可以从test_func中删除该f参数,而将函数本身作为模板参数传递

template<void(&f)()>
void test_func(bool b)
{
    if(b)
        f();
}
然后像这样使用:

data[0]=test_func(?,s3);  // error
data[0] = test_func<s1>;
函数指针和引用通过以下方式明确允许作为模板非类型参数:

非类型模板参数应具有以下之一: 可选cv限定类型:

[……]

指向对象的指针或指向函数的指针, 对对象的左值引用或对函数的左值引用,
这不就是std::function fooF f{return[]bool b{test_funcb,f;};}吗?现在,最好的解决方案就是简单地使用lambda函数。bind试图做到这一点,但使用它需要为任何阅读代码的人学习它的迷你语言,并且往往使编译器更难优化。此外,它的长度几乎不比lambda函数短。@melpomene,你如何将它融入到这段代码中?@Justin,函数能返回lambda吗?与combinetest_func类似,s3@ar2015 data[0]=foos3;这不就是std::function fooF f{return[]bool b{test_funcb,f;};}吗?现在,最好的解决方案就是简单地使用lambda函数。bind试图做到这一点,但使用它需要为任何阅读代码的人学习它的迷你语言,并且往往使编译器更难优化。此外,它的长度几乎不比lambda函数短。@melpomene,你如何将它融入到这段代码中?@Justin,函数能返回lambda吗?与combinetest_func类似,s3@ar2015 data[0]=foos3;样板错误:ISO C++禁止声明“功能”,不需要多谢。这个解决方案也可以扩展到std::function?模板吗?错误:ISO C++禁止声明“功能”,不需要多谢。这个解决方案也可以扩展到std::function吗。它也可以由std::function而不是指针来完成吗?@ar2015-否。因为对于初学者来说,std::function不能是常量表达式。它具有允许类型擦除的状态。函数指针之所以被允许,是因为在某种意义上,它在编译时也是固定的。这是否意味着指针在优化方面优于std::function?@ar2015-我们不能做出这样一个笼统的声明。函数的存在是为了解决一个特定的问题。当然,这不是没有开销,但是
用常规函数做不到这一点。我能看到的唯一明显的改进是,如果函数可以内联,编译器将从模板参数的函数引用中看到它,就像您直接在模板体中编写一样。@ar2015-但您应该首先关注正确性。过早的优化和对它的关注是许多软件问题的根源。它也可以由std::function而不是指针来完成吗?@ar2015-否。因为对于初学者来说,std::function不能是常量表达式。它具有允许类型擦除的状态。函数指针之所以被允许,是因为在某种意义上,它在编译时也是固定的。这是否意味着指针在优化方面优于std::function?@ar2015-我们不能做出这样一个笼统的声明。函数的存在是为了解决一个特定的问题。当然,这不是没有开销的,但是使用常规函数是无法做到的。我能看到的唯一明显的改进是,如果函数可以内联,编译器将从模板参数的函数引用中看到它,就像您直接在模板体中编写一样。@ar2015-但您应该首先关注正确性。过早优化和对它的关注是许多软件问题的根源。