为什么C++20的requires表达式判断类型完整性未按预期工作?
问题成因
这个报错的根本原因是C++的模板实例化规则约束:
- 类模板在第一次以某组特定实参被使用时,就会在当前代码位置完成实例化,生成唯一对应的特化版本。
- C++的单定义规则(ODR)要求同一组模板实参对应的特化在全局只能有一个实例,后续所有对该特化的引用都会直接复用第一次的实例化结果,不会重新计算。
对应到你的代码逻辑:
#include <type_traits> template<typename T> struct IsComplete final : std::bool_constant<requires{sizeof(T);}> {}; int main() { struct A; static_assert(!IsComplete<A>::value); // 1 struct A{}; static_assert(IsComplete<A>::value); // 2 }
- 执行标记1的
static_assert时,A还处于前向声明的不完整状态,编译器此时第一次实例化IsComplete<A>,requires{sizeof(T);}检查不通过,所以IsComplete<A>::value被固定为false。 - 后续你定义了完整的
struct A,但IsComplete<A>的实例已经生成,不会再重新执行sizeof检查,标记2处取到的value仍然是false,自然触发static_assert报错。
如果你需要在代码的不同位置动态判断某个类型是否完整,不要用类模板存储判断结果,可以直接在需要检查的位置就地写requires表达式,避免实例缓存问题:
#define IS_COMPLETE(T) requires{sizeof(T);} int main() { struct A; static_assert(!IS_COMPLETE(A)); // 检查通过 struct A{}; static_assert(IS_COMPLETE(A)); // 检查通过 }
内容的提问来源于stack exchange,提问作者xmllmx
相关产品推荐
相关产品推荐

