如何通过和执行匿名函数在C ++ 11的参数?(How to pass and execute an

2019-08-31 14:21发布

我在寻找的代码是一样以下。

bool Func1(int Arg1, C++11LambdaFunc Arg2){
    if(Arg1 > 0){
        return Arg2(Arg1);
    }
}

后来,我将使用这个代码。

Func1(12, [](int D) -> bool { ... } );

Answer 1:

基本版本,在头文件中使用:

template<typename Lambda>
bool Func1(int Arg1, Lambda Arg2){ // or Lambda&&, which is usually better
  if(Arg1 > 0){
    return Arg2(Arg1);
  } else {
    return false; // remember, all control paths must return a value
  }
}

更复杂的版本,如果你想从你的实现(在其运行时间成本)划分接口:

bool Func1(int Arg1, std::function<bool(int)> Arg2){
  if(Arg1 > 0){
    return Arg2(Arg1);
  } else {
    return false; // remember, all control paths must return a value
  }
}

std::function使用类型擦除,以创建一个在你拉姆达一个自定义创建的包装,然后暴露了使用非虚拟接口pImpl模式把它转发到自定义创建包装。 1

或者,在更短的技术术语, std::function<bool(int)>是可以包装几乎任何你能像调用一个函数,传递一个参数是传递一个兼容的类int ,并返回的东西是与返回兼容的bool

通过调用std::function有一个运行时的成本约等于一个virtual函数调用(由上述类型擦除),并在创建它,它必须复制传入的函数对象(又名仿函数)的状态(可以是廉价的 - 无状态的lambda,或lambda表达式通过引用捕获参数 - 或昂贵的在另一些情况下),并存储它(通常在自由存储区或堆,其具有成本),而纯模板版本可以被“内联”在呼叫的点(即,不仅成本不到一个函数调用,编译器甚至可以在最优化的函数调用和返回的界限!)

第一示例的花式版本还处理一些极端情况更好一点点:(也必须在头文件内实现,或者在相同的翻译单元,因为它是使用)

template<typename Lambda>
bool Func1(int Arg1, Lambda&& Arg2){
  if(Arg1 > 0){
    return std::forward<Lambda>(Arg2)(Arg1);
  } else {
    return false; // remember, all control paths must return a value
  }
}

它使用一种被称为“完美转发”的技术。 对于一些函子,这产生比#1(并且通常更正确的行为)略有不同的行为。

大部分的改善来形成使用&&参数列表:这意味着对仿函数的引用中(而不是复制)获得通过,节约一些成本,同时允许一个const或非const仿函数传递在。

std::forward<Lambda>(...)的变化只会导致行为的改变,如果有人使用了较新的C ++功能,允许方法(包括operator()覆盖上的右值/左值状态this指针。 从理论上讲,这可能是有用的,但实际上超越基于对右值状态我见过仿函数的数量this0 。 当我在写严肃库代码(TM)我去这个麻烦,但很少不然。

还有就是要考虑一个更可能的事情。 假设你要取,要么返回一个函数bool ,或者返回功能void ,并且如果该函数返回void ,你要正确对待它,仿佛它返回true 。 举个例子,你正在一个遍历集合一些时被调用的函数,并希望有选择地支持早期停止。 该函数返回false ,当它想过早停止,和truevoid ,否则。

或者,在更一般的情况下,如果你有一个函数,其中一个需要的功能和其他需要在同一地点一些其他类型的多个覆盖。

这是可能的,这是因为据我要进入这里(或者与智能适配器,或通过SFINAE技术)。 但是,你可能关闭只是创建了两个不同的命名功能更好,因为所需的技术手法过重的重量。


1个技术上std::function可以使用魔仙尘做它,因为它的行为是由标准的描述,而不是它的实现。 我描述一个简单的实现近似于行为std::function实现我与互动。



Answer 2:

第一个解决方案:

你可以让你Func1()函数的函数模板

template<typename T>
bool Func1(int Arg1, T&& Arg2){
    if(Arg1 > 0){
        return Arg2(Arg1);
    }

    return false; // <== DO NOT FORGET A return STATEMENT IN A VALUE-RETURNING
                  //     FUNCTION, OR YOU WILL GET UNDEFINED BEHAVIOR IF FLOWING
                  //     OFF THE END OF THE FUNCTION WITHOUT RETURNING ANYTHING
}

然后,您可以调用它,你的愿望:

int main()
{
    Func1(12, [](int D) -> bool { return D < 0; } );
}

解决方法二:

如果你不想使用模板,另一种(这将带来一些运行时的开销)是使用std::function

#include <functional>

bool Func1(int Arg1, std::function<bool(int)> Arg2){
    if(Arg1 > 0){
        return Arg2(Arg1);
    }

    return false;
}

再次,这将允许您调用Func1()你想要的方式:

int main()
{
    Func1(12, [](int D) -> bool { return D < 0; } );
}


Answer 3:

对于那些口味比较传统,注意,非捕捉-lambda表达式可以转化为函数指针。 所以,你可以写上面的功能:

bool Func1(int Arg1, bool (*Arg2)(int)) { ... }

它会正常工作的传统功能 lambda表达式。



文章来源: How to pass and execute anonymous function as parameter in C++11?