【问题标题】:Why can't lambda, when cast to function pointer, be used in constexpr context?为什么 lambda 在转换为函数指针时不能在 constexpr 上下文中使用?
【发布时间】:2017-05-02 10:30:20
【问题描述】:

考虑一个例子:

template <void (*Foo)()>
struct S {
};

int main() {
    struct A {
        static void x() { }
    };
    S<&A::x> s;
}

代码在clang中编译,gcc认为x没有链接...... 对于使用 lambda 表达式时非常相似的示例:

template <void (*Foo)()>
struct S {
};

int main() {
    auto lambda = []{};
    S<+lambda> s;
}

gcc 和 clang 都同意不编译代码:根据 gcc,一元 + 返回的函数没有链接,而 clang 则相反,该函数的强制转换运算符未声明为 constexpr。是否有任何理由禁止在 constexpr 上下文中使用 lambda 转换为函数指针?

查找编译器和现场演示产生的以下错误:

gcc:

prog.cc:7:14: 错误:'main()::::_FUN' 不是类型'void (*)()' 的有效模板参数,因为'static constexpr void main()::: :_FUN()' 没有链接

clang:

prog.cc:7:8: 注意:非 constexpr 函数 'operator void (*)()' 不能在常量表达式中使用

【问题讨论】:

  • lambda 没有链接,因为eel.is/c++draft/basic.link#8 当然operator() 不是constexpr,所以这是首先发出什么错误的问题 - 我错了吗?跨度>
  • @skypjack 经过一番搜索后,我得出了相同的结论(这与 A 没有链接的原因相同)。而且,除此之外,没有链接的类型不能用作模板参数。

标签: c++ lambda language-lawyer constexpr


【解决方案1】:

Clang hasn't implemented constexpr lambdas yet.

GCC 在其他方面落后。 [temp.arg.nontype]/2 唯一有趣的约束是参数应该是一个常量表达式。但是[expr.const]/(5.2) 使它成为一个,所以这是完全有效的。可能 GCC 还没有实现N4198,这消除了链接要求。

请注意,constexpr lambda 和无链接函数指针模板参数都是 C++14 后的特性。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
  • 2016-11-19
  • 2015-03-26
  • 2016-08-07
相关资源
最近更新 更多