简体   繁体   English

C ++ 11中的函数签名差异

[英]Function signature differences in C++11

Considering C++11's lambdas with the following code, 考虑使用以下代码的C ++ 11的lambdas,

template <typename M>
void call(void (*f)(M), M m)
{
  f(m);
}

int main()
{
  call<int>([](int n) { }, 42);          // OK

  int r;
  call<int>([&](int n) { r = n; }, 42);  // KO
}

is there a signature difference between the lambdas that makes the second one incompatible with the argument of call ? lambda之间是否存在签名差异,使得第二个与call的参数不兼容?

I use g++ 4.6.1. 我用的是g ++ 4.6.1。

Side question: why can't the parameter be inferred if I write call([](int n) { }, 42); 旁边的问题:如果我写call([](int n) { }, 42);为什么不能推断参数call([](int n) { }, 42); ?

Only a captureless lambda can be implicitly converted to function pointer. 只有无捕获的lambda可以隐式转换为函数指针。

A lambda that captures variables cannot be converted to a function pointer because it has state that needs to be maintained (the captured variables) and that state cannot be represented by a function pointer. 捕获变量的lambda无法转换为函数指针,因为它具有需要维护的状态(捕获的变量),并且该状态不能由函数指针表示。

The type M cannot be inferred from the function arguments because a conversion is required to convert the lambda to a function pointer. 无法从函数参数推断出类型M因为需要转换才能将lambda转换为函数指针。 That conversion inhibits template argument deduction. 该转换禁止模板参数推断。 If you were to call the function call with an actual function (eg, void f(int) ), argument deduction would work just fine. 如果你用实际函数调用函数call (例如, void f(int) ),那么参数推导就可以了。

As James already answered, only captureless lambdas can be converted to function pointers. 正如詹姆斯已经回答的那样,只有无法捕获的lambdas可以转换为函数指针。 Lambdas that have state create functor objects that implement operator() , and member function pointers are incompatible with free function pointers. 具有状态的Lambdas创建实现operator() functor对象,并且成员函数指针与自由函数指针不兼容。

When the compiler processes: [&](int n){ r = n; } 编译器处理时: [&](int n){ r = n; } [&](int n){ r = n; } it generates something like: [&](int n){ r = n; }它会产生这样的:

class __annonymous_lambda_type {
   int & r;
public:
   __annonymous_lambda_type( int & r ) : r(r) {}
   void operator()( int n ) const {
      r = n; 
   }
} __lambda_instatiation;

The class is required to store the state of the lambda, in this case the reference to the external object that will be modified when the lambda is executed. 该类需要存储lambda的状态,在这种情况下是对执行lambda时将被修改的外部对象的引用。 That void operator()(int) cannot be bound to a void (*)(int) . void operator()(int)不能绑定到void (*)(int)

On the other hand, if the lambda is stateless, it can be implemented as a free function, like in the case []( int n ) { std::cout << "Hi" << n << std::endl ; } 另一方面,如果lambda是无状态的,它可以实现为自由函数,就像在[]( int n ) { std::cout << "Hi" << n << std::endl ; } []( int n ) { std::cout << "Hi" << n << std::endl ; }

void __annonymous_lambda_function( int n ) {
   std::cout << "Hi " << n << std::endl;
}

Because the lambda does not need to keep any state at all, and as such it can be kept as a plain function. 因为lambda根本不需要保持任何状态,因此它可以保持为普通函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM