C++中`requires A`与`requires (A)`是否等价?标准合规性问询
关于C++模板requires子句括号导致的匹配问题
问题背景
该讨论最初发起于llvm/llvm-project#60377。反复阅读C++标准的temp.constr.atomic和temp.constr.normal章节后,因英文水平有限,对该问题愈发困惑。
为了让clang-format正确格式化requires子句而添加括号后,修改代码风格时出现意外错误,示例代码如下:
#include <concepts> template <typename T> requires std::integral<T> struct [[nodiscard]] Widget; template <typename T> requires(std::integral<T>) // error: Requires clause differs struct [[nodiscard]] Widget { T value; }; [[nodiscard]] auto main() -> int { Widget<int> widget{1}; return widget.value; }
不同编译器测试结果:
- x86_64 clang(最新版):报错
- x86_64 gcc(最新版):编译通过
- x64 msvc v19.latest:报错
请问根据C++标准,clang/msvc和gcc中哪一个的行为符合预期?
结论与标准依据
根据C++标准,clang和MSVC的行为符合预期,gcc的行为不符合标准。
C++标准要求,模板的声明与定义的约束必须是等价的才能匹配。对于原子约束的等价性判断,语法结构是重要依据:带括号的(std::integral<T>)和不带括号的std::integral<T>属于不同的表达式结构,因此对应的原子约束并不等价。
具体来说,requires(std::integral<T>)中的括号使表达式成为括号表达式,而requires std::integral<T>是简单的概念实例化表达式。按照标准中约束等价性的规则,这两个约束不被视为等价,因此模板声明与定义的约束不匹配,编译器应当报错。
内容的提问来源于stack exchange,提问作者FeignClaims
相关产品推荐
相关产品推荐

