类模板中单独使用带参数的C++ requires约束无法编译的问题
问题解析:为何单独使用requires子句编译失败,添加逻辑与后正常?
问题重现
以下代码无法在Clang、GCC、MSVC中编译:
template<typename T> requires(T t) { typename T::name; } class MyVector { };
各编译器报错信息:
--- Clang ---- <source>:9:14: error: 'T' does not refer to a value requires(T t) { typename T::name; } ^ <source>:8:19: note: declared here template<typename T> ^ --- GCC ---- <source>:9:16: error: expected primary-expression before 't' 9 | requires(T t) { typename T::name; } --- MSVC ---- <source>(9): error C2760: syntax error: 't' was unexpected here; expected ')' <source>(9): error C2059: syntax error: ')'
但添加逻辑与表达式后,代码可正常编译:
template<typename T> requires std::is_integral_v<T> && requires(T t) { typename T::name; } class MyVector{};
仅添加true &&也能正常编译:
template<typename T> requires true && requires(T t) { typename T::name; } class MyVector{};
核心原因:语法歧义与requires的两种用法
问题出在C++语法对requires的解析歧义上,先明确两个关键概念:
- requires子句:直接用于模板约束的语法,形式为
requires { ... }或requires(参数列表) { ... },但它不能直接作为requires关键字后的唯一内容——因为这会和另一种用法混淆。 - requires表达式:可求值的布尔表达式,形式为
requires(参数列表) { ... },它可以出现在任何布尔表达式合法的位置(比如逻辑运算的操作数中)。
单独写法失败的原因
当你直接写requires(T t) { typename T::name; }时,编译器会优先将requires后的(T t)解析为表达式的起始部分,而非requires子句的参数列表。此时T是模板类型参数,不是可用于表达式的值,因此触发各编译器的语法错误。
添加逻辑与后成功的原因
添加true &&后,整个requires后面的内容变成了完整的布尔表达式,其中的requires(T t) { ... }会被明确解析为requires表达式(作为逻辑与的右侧操作数),此时语法完全合法,编译器能正确识别这是可求值的约束条件,因此编译通过。
单独使用的正确写法
如果想单独用requires实现该约束,需要用双重requires:第一个requires是模板约束的关键字,第二个requires用于引入requires表达式,写法如下:
template<typename T> requires requires(T t) { typename T::name; } class MyVector { };
内容的提问来源于stack exchange,提问作者Ajay
相关产品推荐
相关产品推荐

