Clang拒绝std::array初始化而GCC/MSVC接受,哪个编译器合规?
用户自定义字面量编译分歧:Clang vs GCC/MSVC
我正在学习用户自定义字面量,编写了如下代码,该代码可在GCC和MSVC中正常运行,但Clang拒绝编译,想了解哪个编译器的行为符合标准。
#include <array> template<std::size_t N> struct Literal { std::array<char, N> arr; constexpr Literal(char const(&pp)[N]): arr(""){} }; template<Literal> constexpr auto operator""_S() { return 4; } int main() { auto i = "test"_S; auto j = "ch"_S; }
Clang的错误信息如下:
<source>:7:48: error: initializer-string for char array is too long, array size is 3 but initializer has size 5 (including the null terminating character) 7 | constexpr Literal(char const(&pp)[N]): arr(""){} | <source>:17:15: note: in instantiation of member function 'Literal<3>::Literal' requested here 17 | auto j = "ch"_S;
问题分析
核心矛盾点在于构造函数中arr("")的初始化逻辑:
std::array<char, N>是聚合类型,C++20及以后标准允许通过小括号进行聚合初始化;在此之前仅支持大括号初始化。- 用字符串字面量
""(仅含1个空终止符,长度为1)初始化std::array<char, N>时,若N > 1,剩余元素会被值初始化为0,这完全符合C++标准对字符数组初始化的规定。
Clang报错称"初始化字符串过长"是不合理的——""的长度仅为1,远小于实例化Literal<3>时数组的大小3,不存在长度超限的问题。
结论
GCC和MSVC的行为符合C++标准,Clang的报错属于编译器实现bug。
若要避免跨编译器问题,可将构造函数中的初始化改为大括号形式(兼容更早C++标准):
constexpr Literal(char const(&pp)[N]): arr{""} {}
内容的提问来源于stack exchange,提问作者user20562802
相关产品推荐
相关产品推荐

