为何含不可拷贝元素的std::vector被std::copyable判定为可拷贝?
问题:不可拷贝元素的vector为何通过std::copyable断言?
先看代码:
#include<concepts> #include<vector> struct nc { nc(const nc&) = delete; }; static_assert(!std::copyable<nc>); // 符合预期,断言通过 static_assert(!std::copyable<std::vector<nc>>); // 意外失败,断言不通过
实际尝试拷贝std::vector<nc>时编译失败:
std::vector<nc> v; std::vector<nc> w = v; // 编译错误
这是标准规定的预期行为,不是编译器或标准库的bug,原因如下:
std::copyable的核心要求是类型满足std::copy_constructible(可拷贝构造)和std::movable(可移动)。- 对于模板类
std::vector<T>,它的拷贝构造函数在模板声明中是存在的,但该构造函数的实际可用性依赖于元素类型T是否可拷贝。 - 当检查
std::copyable<std::vector<nc>>时,编译器仅做声明层面的概念检查,不会实例化vector<nc>的拷贝构造函数。此时编译器看到vector模板中确实有接受const vector&参数的拷贝构造函数声明,因此认为std::copy_constructible<std::vector<nc>>成立,进而std::copyable断言通过。 - 只有当你实际尝试拷贝
vector<nc>时,编译器才会实例化它的拷贝构造函数,此时发现元素nc不可拷贝,才会触发编译错误。
简单来说:概念检查看的是“有没有这个构造函数的声明”,而实际拷贝看的是“这个构造函数实例化后能不能用”,两者的检查阶段不同,所以出现了看似矛盾的结果。
内容的提问来源于stack exchange,提问作者Nikola Benes
相关产品推荐
相关产品推荐

