编写一个接受 lambda 表达式作为参数的函数

发布于 2024-09-08 11:46:49 字数 794 浏览 4 评论 0原文

我有一个这样的方法

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; 
}

,想法是你可以这样调用它

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; 
        }
    );
}

但是我收到错误:没有函数模板“VlcFunctional::mapMapValues”的实例与参数列表参数类型匹配:(std::map, std ::allocator>>,__lambda1)

知道我做错了什么吗? Visual Studio 2008 和英特尔 C++ 编译器 11.1

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)

Any idea what I'm doing wrong? Visual Studio 2008 and Intel C++ compiler 11.1

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

沉睡月亮 2024-09-15 11:46:49

您的函数需要一个函数指针,而不是 lambda。

在 C++ 中,通常有 3 种类型的“可调用对象”。

  1. 函数指针。
  2. 函数对象。
  3. 拉姆达函数。

如果您希望能够在函数接口中使用所有这些,那么您可以使用 std::function :

template<typename T, typename U> 
map<T,U> mapMapValues(map<T,U> old, std::function<T(T, U)> f)
{
    ...
}

这将允许使用上述三种类型的可调用对象中的任何一种来调用函数。然而,这种便利的代价是函数调用的少量开销(通常是空指针检查,然后通过函数指针进行调用)。这意味着该函数几乎肯定不是内联的(除非使用高级 WPO/LTO)。

或者,您可以添加额外的模板参数来为第二个参数采用任意类型。这会更有效,但你会失去所使用函数的类型安全性,并可能导致更多的代码膨胀。

template<typename T, typename U, typename F> 
map<T,U> mapMapValues(map<T,U> old, F f) 

Your function is expecting a function pointer, not a lambda.

In C++, there are, in general, 3 types of "callable objects".

  1. Function pointers.
  2. Function objects.
  3. Lambda functions.

If you want to be able to use all of these in your function interface, then you could use 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).

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) 
赢得她心 2024-09-15 11:46:49

您的参数类型声明 T (f)(T,U) 的类型为“自由函数,采用 TU 并返回 <代码>T'。您不能向其传递 lambda、函数对象或除具有该签名的实际函数之外的任何内容。

您可以通过将参数类型更改为 std::function 来解决此问题,如下所示:

template<typename T, typename U> 
map<T,U> mapMapValues(map<T,U> old, std::function<T(T,U)>)
{
}

或者,您可以将函数类型声明为模板参数,如下所示:

template<typename T, typename U, typename Fn> 
map<T,U> mapMapValues(map<T,U> old, Fn fn)
{
  fn(...);
}

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.

You could solve this by changing the type of the parameter to std::function<T(T,U)> like this:

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(...);
}
小猫一只 2024-09-15 11:46:49

我想贡献这个简单但不言自明的例子。它展示了如何将“可调用的东西”(函数、函数对象和 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 ();

} // ()

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.

// 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 ();

} // ()
小梨窩很甜 2024-09-15 11:46:49

根据 n3052。然而,这个功能似乎没有在 VC++ 中实现,只有部分在 g++ 中实现,请参阅我的 SO 问题

Lambda expressions with empty capture list should decay to function pointers, according to n3052. However it seems that this feature is not implemented in VC++ and only partially in g++, see my SO question.

素罗衫 2024-09-15 11:46:49

这是如何将函数作为参数传递的一些示例

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 );

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 );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文