c++ - 为什么 C++20 的 requires 表达式不符合预期?
问题描述
#include <type_traits>
template<typename T>
struct IsComplete final
: std::bool_constant<requires{sizeof(T);}>
{};
int main()
{
struct A;
static_assert(!IsComplete<A>::value); // ok
struct A{};
static_assert(IsComplete<A>::value); // error
}
我预计第二个static_assert
应该是真的,因为 A 现在是一个完整的类型。
为什么 C++20 的 requires 表达式不符合预期?
解决方案
这是一个错误的期望。首先,类模板在翻译单元中只有一个实例化点:
[温度点]
7 ...类模板的特化在翻译单元内最多有一个实例化点。任何模板的特化都可能在多个翻译单元中具有实例化点。如果根据单一定义规则,两个不同的实例化点赋予模板特化不同的含义,则程序是非良构的,不需要诊断。
模板从不允许程序中的两个点对同一组参数的模板有不同的解释(一般情况下的 ODR 噩梦)。您基本上是通过尝试该特征开始冒险进入鼻恶魔领域。
如果你认为使用 C++20 概念会改变任何东西,你就会陷入格式错误的问题;如果您对示例进行概念化,则无需诊断区域
template<typename T>
concept IsComplete = requires{sizeof(T);};
int main()
{
struct A;
static_assert(!IsComplete<A>); // ok
struct A{};
static_assert(IsComplete<A>); // error or nuclear launch.
}
[临时名称]
8 ... 如果指定的模板参数满足概念的规范化约束表达式 ([temp.constr.constr]),则概念 ID 评估为 true,否则为 false。
[temp.constr.atomic]
3 ...如果在程序的不同点,相同的原子约束和模板参数的满足结果不同,则程序格式错误,不需要诊断。
这不是什么新东西,概念只是增加了更多相同的东西。如果参数的某些属性在程序中的两个不同点不同,则模板对特定参数集的含义不得改变。
因此,虽然可以编写一个检查类型是否完整的概念(即使在 C++20 之前的 SFINAE 黑客中),但粗心地使用它就是在玩火。
推荐阅读
- node.js - Jwt 认证/授权技巧
- laravel - 如何在 Laravel 7 中显示每个类别的帖子数?
- ios - RTCAudioSession 将 MicrophoneBuiltIn 显示为输入端口,尽管蓝牙设备已在 iOS 中连接
- python - 与存储在 Pandas 数据框中的点的 XY 位置相比,根据数组内的单元格位置 (XY) 对 numpy 数组应用计算
- instruments - 如何匹配自定义 Instruments 启动模式中的字符串?
- c++ - 遇到 MFC 序列化问题
- ios - 在 Swift 5 中,如何通过背景音频将音频控件添加到控制中心?
- python-3.x - 遍历数组并在对象内部搜索
- c - 无法理解程序的输出
- django - 如何在本地环境中运行没有媒体文件的 django 管理应用程序?