C++中带指定捕获的lambda对象构造方法及编译器扩展可行性问询
问题背景
从C++20开始,无捕获的闭包类型拥有默认构造函数:
若未指定任何捕获,则闭包类型拥有默认的默认构造函数。
对于带有捕获的闭包类型,除了使用std::bit_cast(前提是闭包类型可平凡复制)构造外,Visual Studio编译器额外支持直接传入捕获对应类型的值构造闭包对象,示例代码如下:
#include <bit> int main() { int x = 0; using A = decltype([x](){ return x; }); // 所有编译器均支持 constexpr A a = std::bit_cast<A>(1); static_assert( a() == 1 ); // 仅MSVC支持 constexpr A b(1); static_assert( b() == 1 ); }
目前Clang和GCC均不支持A b(1)这类写法,这是因为C++标准并未强制要求闭包类型提供这类构造函数。
问题解答
编译器完全可以将这类构造函数作为扩展功能提供,该行为符合C++标准的规则。
- C++标准仅约束符合标准的用户程序的行为,要求所有合规程序在符合标准的编译器实现上运行时得到标准规定的结果,并未禁止编译器在不破坏合规程序正确性的前提下,提供额外的非标准功能。
- 针对闭包类型,C++标准仅明确了其必须具备的强制成员(比如无捕获闭包的默认构造函数、对应签名的调用运算符、符合平凡性要求的复制/移动构造函数等),没有禁止实现为闭包类型额外添加非标准的构造函数。只要这类扩展不会导致原本符合标准的代码出现编译错误、或是运行结果不符合标准要求,就属于合法的编译器扩展。
- Clang、GCC目前未提供这类构造函数,只是编译器实现选择的差异,并不代表这类扩展违反标准要求。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

