Lambda中constexpr代码Clang编译报错,GCC/MSVC正常,是否为Clang Bug?
Clang编译C++代码报错,但GCC/MSVC正常运行的问题解析
这段C++代码在GCC和MSVC环境下能正常编译运行,但用Clang编译时会报错,报错指向std::string内部union成员的常量表达式赋值问题。
问题代码
#include <iostream> #include <string> #include <type_traits> constexpr bool do_tests() { // 运行时测试失败则打印错误信息 auto verify = [](bool test, std::string message = "error") { if (!std::is_constant_evaluated() && !test) std::cout << message << '\n'; return test; }; return verify(1 == 1, "test"); }; int main() { constexpr bool b = do_tests(); std::cout << b << '\n'; }
Clang报错信息
basic_string.h:356:10: note: 对无活跃成员的union的成员'_M_local_buf'赋值,不允许在常量表达式中进行
问题原因
问题出在verify lambda的std::string默认参数上。当do_tests()被作为常量表达式求值(比如constexpr bool b = do_tests();)时,Clang严格遵循C++标准:此时std::string的构造过程会涉及到对其内部union成员的赋值,但该union此时没有活跃成员,这违反了常量表达式的规则。
GCC和MSVC在这个场景下做了宽松处理,允许这种操作,但Clang的行为是符合C++标准要求的,并非Bug。
解决方案
将lambda的参数类型从std::string改为const char*,这样在常量表达式求值时不会触发std::string的构造,彻底避免这个问题。修改后的代码如下:
#include <iostream> #include <string> #include <type_traits> constexpr bool do_tests() { // 运行时测试失败则打印错误信息 auto verify = [](bool test, const char* message = "error") { if (!std::is_constant_evaluated() && !test) std::cout << message << '\n'; return test; }; return verify(1 == 1, "test"); }; int main() { constexpr bool b = do_tests(); std::cout << b << '\n'; }
这段代码在Clang、GCC和MSVC中都能正常编译运行,因为const char*字面量属于合法的常量表达式,只有在运行时需要打印错误信息时,才会将其输出到控制台,不会触发std::string的常量构造问题。
内容的提问来源于stack exchange,提问作者doug
相关产品推荐
相关产品推荐

