You need to enable JavaScript to run this app. C++20中std::reference_wrapper<void>为何不会触发编译错误?
优惠活动
大模型
产品
解决方案
定价
更多

C++20中std::reference_wrapper<void>为何不会触发编译错误?

问题原因分析

核心原因是类模板约束的作用位置不同,以及C++对「指向不完整类型的指针」的语法许可,具体分两点说明:

1. 自定义模板A报错的原因

你给A加的requires约束是类模板顶层关联约束,C++20标准规定:只要你在代码中命名了A<T>这个特化类型,不管你是否需要实例化该类、是否只用到它的指针,都必须先检查类模板的顶层约束是否满足。
A<void>直接触发了!std::is_void_v<T>的约束检查,约束不满足直接编译错误,和你是否声明指针无关。

2. std::reference_wrapper<void>*不报错的原因

标准库的std::reference_wrapper没有设置类模板顶层约束,所有和类型合法性相关的约束都只作用在它的成员函数上(比如构造函数、get()方法、operator()重载)。
这意味着std::reference_wrapper<void>这个类型名本身是合法的,属于未实例化的不完整类型。而C++语法一直允许声明指向不完整类型的指针,不需要该类型完全实例化、也不需要检查成员函数的约束,所以std::reference_wrapper<void>* p2{}的声明不会触发任何约束检查,自然不会报错。

验证示例

如果你尝试创建std::reference_wrapper<void>的实例,就会触发成员函数的约束检查,得到预期的编译错误:

std::reference_wrapper<void> r; // 编译报错,符合预期

同理,如果你把自定义模板A的约束从类顶层移到构造函数上,A<void>*的声明也不会报错:

template<typename T>
struct A {
    A() requires (!std::is_void_v<T>) = default;
};
A<void>* p1{}; // 不再报错,和reference_wrapper行为一致

内容的提问来源于stack exchange,提问作者xmllmx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 04:42:03