我可以使用C 17无捕获lambda constexpr转换运算符的结果作为函数指针模板非类型参数吗?

回答How do I write a lambda expression that looks like a method?时,我试图通过利用这样一个事实将无捕获的lambda变成成员函数指针,因为从C17开始,无捕获的lambdas有一个constexpr转换运算符到它们的函数指针类型.

所以我提出了一个问题,沸腾到:

template<void(*)()> struct A{};

int main()
{
  A<static_cast<void(*)()>([]{})>{}; // 1

  constexpr auto fp = static_cast<void(*)()>([]{});
  A<fp>{}; // 2
}

现在,这编译在clang(从5.0.0开始),但gcc(> = 7.2)抱怨:

error: lambda-expression in template-argument
   A<static_cast<void(*)()>([]{ /*whatever*/ })>{}; // 1
                            ^
error: 'main()::<lambda()>::_FUN' is not a valid template argument for type 'void (*)()' because 'static constexpr void main()::<lambda()>::_FUN()' has no linkage
   A<fp>{}; // 2

问题是,谁是对的?

最佳答案
这是一个gcc bug,提交了83258.

在C 14中,我们曾经有一个linkage requirement用于指针类型的非类型模板参数.但是在C 17中(作为N4268的结果),参数只需要是正确类型的converted constant expression,还有一些其他限制(这里没有任何限制).一旦我们可以构造fp,我们应该能够将它用作模板参数.

转载注明原文:我可以使用C 17无捕获lambda constexpr转换运算符的结果作为函数指针模板非类型参数吗? - 代码日志