定义自定义析构函数的C++类为何仍满足std::movable约束
问题原因分析
核心误区
你对「用户自定义析构会抑制移动操作生成」的C++规则理解正确,但对std::movable约束的定义存在误解,这是编译失败的根本原因。
std::movable的官方定义
C++20中std::movable<T>的等价判断逻辑如下:
template<class T> concept movable = std::is_object_v<T> && std::is_move_constructible_v<T> && std::is_assignable_v<T&, T&&> && std::is_swappable_v<T>;
其中最容易被忽略的特性是:当类没有可用的移动构造/移动赋值时,只要拷贝构造/拷贝赋值可用,右值参数可以匹配到拷贝操作的const T&形参,此时std::is_move_constructible_v<T>和std::is_assignable_v<T&, T&&>仍会返回true。
代码不符合约束的原因
你的两个版本的Widget类都符合以下特性:
- 用户声明了析构函数,编译器不会自动生成移动构造、移动赋值运算符
- 编译器仍会隐式生成默认的拷贝构造、拷贝赋值运算符(该特性从C++11起已被标记为弃用,但仍符合标准兼容要求)
因此std::movable<Widget>的判断结果为true,你定义的!std::movable<T>约束自然不满足,触发编译错误。
解决方案
如果你希望Widget满足!std::movable<T>约束,需要显式删除拷贝构造和拷贝赋值运算符,此时类既不能拷贝也不能移动,即可符合约束要求:
struct Widget { ~Widget() = default; Widget(const Widget&) = delete; Widget& operator=(const Widget&) = delete; };
内容的提问来源于stack exchange,提问作者bielu000
相关产品推荐
相关产品推荐

