考虑一个例子:
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,unary 返回的函数没有链接,clang 相反,函数的强制转换运算符没有声明为 constexpr。有什么理由不允许在 constexpr 上下文中使用 lambda 强制转换为函数指针吗?
查找以下由编译器和现场演示生成的错误:
海湾合作委员会:
prog.cc:7:14:错误:“main()::::_FUN”不是类型“void (*)()”的有效模板参数,因为“static constexpr void main()::::_FUN()”没有链接
铛:
prog.cc:7:8:注意:非constexpr函数“运算符void(*)()”不能在常量表达式中使用
Clang还没有实现constexpr
lambdas。
海湾合作委员会在其他方面落后。[temp.arg.nontype]/2 唯一有趣的约束是参数应该是一个常量表达式。但是 [expr.const]/(5.2) 使它成为一个,所以这是完全有效的。也许GCC还没有实施N4198,这消除了链接要求。
请注意,constexpr
lambda 和无链接函数指针模板参数都是 C 14 后的功能。