C++ 编写一个接受 lambda 表达式作为参数的函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3203305/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Write a function that accepts a lambda expression as argument
提问by Jamie Cook
I have a method like this
我有这样的方法
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, T (f)(T,U))
{
map<T,U> new;
for(auto it = old.begin(); it != old.end(); ++it)
{
new[it->first] = f(it->first,it->second);
}
return new;
}
and the idea is that you'd call it like this
这个想法是你会这样称呼它
BOOST_AUTO_TEST_CASE(MapMapValues_basic)
{
map<int,int> test;
test[1] = 1;
map<int,int> transformedMap = VlcFunctional::mapMapValues(test,
[&](int key, int value) -> int
{
return key + 1;
}
);
}
However I get the error: no instance of function template "VlcFunctional::mapMapValues" matches the argument list argument types are: (std::map, std::allocator>>, __lambda1)
但是我收到错误:没有函数模板“VlcFunctional::mapMapValues”的实例匹配参数列表参数类型是:(std::map, std::allocator>>, __lambda1)
Any idea what I'm doing wrong? Visual Studio 2008 and Intel C++ compiler 11.1
知道我做错了什么吗?Visual Studio 2008 和英特尔 C++ 编译器 11.1
回答by Peter Alexander
Your function is expecting a function pointer, not a lambda.
您的函数需要函数指针,而不是 lambda。
In C++, there are, in general, 3 types of "callable objects".
在 C++ 中,通常有 3 种类型的“可调用对象”。
- Function pointers.
- Function objects.
- Lambda functions.
- 函数指针。
- 函数对象。
- Lambda 函数。
If you want to be able to use all of these in your function interface, then you could use std::function
:
如果您希望能够在您的函数界面中使用所有这些,那么您可以使用std::function
:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T, U)> f)
{
...
}
This will allow the function to be called using any of the three types of callable objects above. However, the price for this convenience is a small amount of overhead on invokations on the function (usually a null pointer check, then a call through a function pointer). This means that the function is almost certainly not inlined (except maybe with advanced WPO/LTO).
这将允许使用上述三种类型的可调用对象中的任何一种来调用函数。然而,这种便利的代价是函数调用的少量开销(通常是空指针检查,然后是通过函数指针的调用)。这意味着该函数几乎肯定不是内联的(除了高级WPO/ LTO)。
Alternatively, you could add an additional template parameter to take an arbitrary type for the second parameter. This will be more efficient, but you lose type-safety on the function used, and could lead to more code bloat.
或者,您可以添加一个额外的模板参数来为第二个参数采用任意类型。这将更有效,但您会失去所使用函数的类型安全性,并可能导致更多的代码膨胀。
template<typename T, typename U, typename F>
map<T,U> mapMapValues(map<T,U> old, F f)
回答by JoeG
Your parameter type declaration T (f)(T,U)
is of type 'free function taking a T
and a U
and returning a T
'. You can't pass it a lambda, a function object, or anything except an actual function with that signature.
您的参数类型声明T (f)(T,U)
属于“自由函数采用 aT
和 aU
并返回 a T
”的类型。除了具有该签名的实际函数之外,您不能将 lambda、函数对象或任何东西传递给它。
You could solve this by changing the type of the parameter to std::function<T(T,U)>
like this:
你可以通过改变参数的类型来解决这个std::function<T(T,U)>
问题:
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T,U)>)
{
}
Alternately, you could declare the function type as a template argument like this:
或者,您可以将函数类型声明为模板参数,如下所示:
template<typename T, typename U, typename Fn>
map<T,U> mapMapValues(map<T,U> old, Fn fn)
{
fn(...);
}
回答by cibercitizen1
I would like to contribute this simple but self-explanatory example. It shows how to pass "callable things" (functions, function objects, and lambdas) to a function or to an object.
我想贡献这个简单但不言自明的例子。它展示了如何将“可调用的东西”(函数、函数对象和 lambda 表达式)传递给函数或对象。
// g++ -std=c++11 thisFile.cpp
#include <iostream>
#include <thread>
using namespace std;
// -----------------------------------------------------------------
class Box {
public:
function<void(string)> theFunction;
bool funValid;
Box () : funValid (false) { }
void setFun (function<void(string)> f) {
theFunction = f;
funValid = true;
}
void callIt () {
if ( ! funValid ) return;
theFunction (" hello from Box ");
}
}; // class
// -----------------------------------------------------------------
class FunClass {
public:
string msg;
FunClass (string m) : msg (m) { }
void operator() (string s) {
cout << msg << s << endl;
}
};
// -----------------------------------------------------------------
void f (string s) {
cout << s << endl;
} // ()
// -----------------------------------------------------------------
void call_it ( void (*pf) (string) ) {
pf( "call_it: hello");
} // ()
// -----------------------------------------------------------------
void call_it1 ( function<void(string)> pf ) {
pf( "call_it1: hello");
} // ()
// -----------------------------------------------------------------
int main() {
int a = 1234;
FunClass fc ( " christmas ");
f("hello");
call_it ( f );
call_it1 ( f );
// conversion ERROR: call_it ( [&] (string s) -> void { cout << s << a << endl; } );
call_it1 ( [&] (string s) -> void { cout << s << a << endl; } );
Box ca;
ca.callIt ();
ca.setFun (f);
ca.callIt ();
ca.setFun ( [&] (string s) -> void { cout << s << a << endl; } );
ca.callIt ();
ca.setFun (fc);
ca.callIt ();
} // ()
回答by rafak
回答by serup
Here is some example of how to pass a function as parameter
这是如何将函数作为参数传递的一些示例
class YourClass
{
void YourClass::callback(void(*fptr)(int p1, int p2))
{
if(fptr != NULL)
fptr(p1, p2);
}
};
void dummyfunction(int p1, int p2)
{
cout << "inside dummyfunction " << endl;
}
YourClass yc;
// using a dummyfunction as callback
yc.callback(&dummyfunction);
// using a lambda as callback
yc.callback( [&](int p1, int p2) { cout << "inside lambda callback function" << endl; } );
// using a static member function
yc.callback( &aClass::memberfunction );