模板函数在与本地lambda一起使用时会导致编译器错误
Template function causes a compiler error when used with local lambda
我之前的问题得出的结论是,使用POSIX makecontext
与c++ lambda函数(即函数对象)可能需要一个令人讨厌的"双强制转换"。继续,我现在面临一个与以下最小代码相关的编译错误:
#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;
}
错误是:
error: invalid cast from type ‘foo() [with T = int]::<lambda(int)>’ to type ‘void (*)(int)’
然而,如果我从foo
函数中删除未使用的(在本例中)模板参数,那么它将成为void foo();
,并将调用更改为foo()
,错误就会消失。有人能告诉我为什么吗?我使用的是g++ 4.6.
从下面的注释来看,上面代码中的[=]
似乎导致lambda成为"捕获"lambda,而不管它实际上没有捕获任何东西。[=]
在我的代码中不是必需的,唉,在GCC 4.6中替换为[]
并不能消除错误。我正在安装GCC 4.6.1…
如果使用[=]
来诱导lambda,则不会得到函数指针(或可转换为函数指针的对象)。您将得到一个函数对象。再多的强制类型转换也不能让你把它传递给makecontext
。这根本行不通。
根据N3291, c++ 0x最新的工作草案:
没有lambda捕获的lambda表达式的闭包类型具有一个公共非虚非显式const转换函数,该转换函数指向与闭包类型的函数调用操作符具有相同形参和返回类型的函数。该转换函数返回的值应为另一个函数的地址,该函数在调用时与调用闭包类型的函数调用操作符具有相同的效果。
这是规范允许转换为函数指针的惟一位置。因此,如果最近版本的GCC允许将[=]转换为函数指针,那是不符合规范的。
只有不可捕获的lambda才可以转换为函数指针;虽然f
在技术上不捕获任何东西,但它确实有一个按值捕获的默认捕获模式(没有明显的原因)。
在f
的声明中将[=]
更改为[]
,它应该可以正常工作。
EDIT:事实上,这与最新版本的GCC(正如Kerrek所指出的)一起编译,这强烈表明这仅仅是您正在使用的版本中的编译器错误。
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++,我收到一个无法理解的编译器错误
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- 重载方法的方式会在使用临时调用时生成编译器错误
- 尝试使用继承和模板实现CRTP.Visual Studio正在生成编译器错误
- 有没有办法让编译器在我放置字符串而不是 nlohmann::json 对象时抛出错误?
- 致命错误 C1001 :vs2017 15.8.4 的内部错误(编译器文件"msc1.cpp",第
- C++2440错误-编译器认为字符串是常量字符
- Clang 错误 – 编译器错误或缺少一些细节?
- 视觉C++ 2017 错误?编译器优化表达式
- 配置:错误:C++编译器无法创建可执行文件
- PHP PDO_ODBC配置:错误:C 编译器无法创建可执行文件
- 致命错误 C1001:内部编译器错误(编译器文件"MSC1.cpp",第 1794 行)
- 错误:编译器限制达到简单hello world程序的堆限制
- c++链接错误:编译器找不到函数的定义
- 生成 CImg 时出现致命错误(编译器限制)
- 抛出对齐类型时出现 Clang 运行时错误.编译器错误