lambda 是不是应该衰减为模板代码中的函数指针?

Posted

技术标签:

【中文标题】lambda 是不是应该衰减为模板代码中的函数指针?【英文标题】:Should lambda decay to function pointer in templated code?lambda 是否应该衰减为模板代码中的函数指针? 【发布时间】:2011-03-10 12:15:40 【问题描述】:

我在某处读到,如果捕获列表为空,则 lambda 函数应衰减为函数指针。我现在能找到的唯一参考是n3052。使用 g++(4.5 和 4.6)它可以按预期工作,除非在模板代码中声明了 lambda。

例如下面的代码编译:

void foo() 
    void (*f)(void) = [];

但是当模板化时它不再编译(如果foo实际上在其他地方被调用):

template<class T>
void foo() 
    void (*f)(void) = [];

在上面的参考资料中,我没有看到对这种行为的解释。这是 g++ 的临时限制吗?如果不是,是否有(技术)理由不允许这样做?

【问题讨论】:

请注意,您引用的 N3052 确实已合并到 C++0x FCD (N3092 5.1.2/6) 中。 Visual C++ 2010 根本没有实现转换(不足为奇,因为允许它的语言在 VC++ 发布之前很快就被纳入标准)。我已经提交了一份关于 Microsoft Connect 的错误报告(尽管我预计在下一个 Visual C++ 版本之前它不会被修复):connect.microsoft.com/VisualStudio/feedback/details/572138/… 仅供参考:英特尔 C++ 11.1 不支持上述代码 它已经在 GCC 的 bugtracker 中,但目前尚未确认:gcc.gnu.org/bugzilla/show_bug.cgi?id=45080 @James Noob 问题(也对提问者)。鉴于函数指针捕获列表对于 lambda 集合是空的,我们可以在不使用 std::function 的情况下将它们存储在容器中(对于我遇到的情况来说很昂贵......)?对此已经两年抱歉了,只是偶然发现了这个页面并且很好奇...... 【参考方案1】:

我想不出任何理由会明确禁止它。我猜这只是g++的暂时限制。

我还尝试了其他一些方法:

template <class T>
void foo(void (*f)(void)) 

foo<int>([]);

这行得通。

typedef void (*fun)(void);

template <class T>
fun foo()  return [];  // error: Cannot convert.

foo<int>()();

不会(但如果 foo 未参数化,则会这样做)。

注意:我只在 g++ 4.5 中测试过。

【讨论】:

是的,在第一种情况下,lambda 是在代码的非模板部分声明的(尽管它被模板函数使用)。在模板类中声明 lambda 时也会出现同样的问题。

以上是关于lambda 是不是应该衰减为模板代码中的函数指针?的主要内容,如果未能解决你的问题,请参考以下文章

C++20:非类型模板参数中的非捕获 lambda

什么是数组到指针衰减?

数组表示法衰减为指针符号 - 仅用于函数参数?

将 lambda 作为模板参数传递给函数指针函数模板化

将 lambda 作为参数传递 - 通过引用或值?

如何使用 C++ lambda 将成员函数指针转换为普通函数指针以用作回调