与本地lambda一起使用时,模板函数会导致编译器错误

use*_*370 5 c++ lambda templates c++11

之前的问题得出的结论是,使用makecontext带有C++ lambda函数的POSIX (即函数对象)可能需要一个令人反感的"双重强制转换" .继续,我现在面临与以下最小代码相关的编译错误:

#include <iostream>
#include <ucontext.h>

using namespace std;

template <typename T> void foo()   {
  ucontext_t c;
  auto f = [=](int i){ cout << i << endl; };
  makecontext(&c, (void (*) (void)) (void (*)(int)) f, 1, 12345);
}

int main(int argc, char *argv[]) {
  foo<int>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误是:

error: invalid cast from type ‘foo() [with T = int]::<lambda(int)>’ to type ‘void (*)(int)’
Run Code Online (Sandbox Code Playgroud)

但是,如果我从foo函数中删除未使用的(在此示例中)模板参数,那么它就变为void foo();,并且更改foo()对错误的调用将消失.有人能告诉我为什么吗?我正在使用G ++ 4.6.

编辑:

从下面的评论中,似乎[=]上面的代码导致lambda成为一个"捕获"lambda,无论它实际上没有捕获任何东西.该[=]不是在我的代码需要,唉用替换[]在GCC 4.6不删除错误.我正在安装GCC 4.6.1 ...

Nic*_*las 5

如果你[=]用来诱导你的lambda,你将不会得到一个函数指针(或一个可转换为一个的对象).你会得到一个功能对象.并且没有任何数量的铸造允许你将其传递给makecontext.不是以任何方式实际工作.

根据N3291,最新的C++ 0x工作草案:

没有lambda-capture的lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数,用于指向具有与闭包类型的函数调用操作符相同的参数和返回类型的函数.此转换函数返回的值应为函数的地址,该函数在调用时具有与调用闭包类型的函数调用运算符相同的效果.

这是规范允许转换为函数指针的唯一位置.因此,如果GCC的最新版本允许转换为[=]的函数指针,则不符合规范.

  • 实际上,`[=]`和`[&]`假设只捕获使用的内容.由于没有使用外部范围,所以它应该起作用,如果它是`[]`. (3认同)