复制存储不可复制构造且不可复制赋值元素的std::vector
复制存储不可复制构造且不可复制赋值元素的std::vector
嘿,这个问题挺有意思的,咱们一步步拆解来看:
首先结论是你没法直接复制这个std::vector<A>,原因出在C++对构造函数匹配的优先级规则上,咱们慢慢说:
- 当你尝试拷贝一个
std::vector<A>时,vector的拷贝构造逻辑会遍历源容器里的每个元素,用const A&类型的参数去构造新容器里的对应元素。 - 你的类
A虽然写了一个泛型构造函数A(auto&&),看起来好像能接受任何类型的参数,但这里有个关键规则:用户显式声明的特殊成员函数(比如你删除的A(const A&)拷贝构造函数),优先级比模板构造函数更高。 - 所以当编译器看到用
const A&构造A的需求时,它会直接匹配你那个被delete的拷贝构造函数,而不是去实例化那个泛型模板构造函数。这就直接导致编译失败——毕竟你明确告诉编译器这个构造函数不能用。
咱们可以用代码验证一下,比如写这么一行:
std::vector<A> v1; std::vector<A> v2 = v1; // 这行代码会编译报错
编译器会提示你尝试调用了被删除的函数A::A(const A&),完全不会用到那个泛型构造函数。
如果真的想实现类似“复制”vector的效果,你得调整A的构造函数约束,比如让泛型构造函数在参数是A类型时也能被选中,但这需要用概念排除掉拷贝构造的匹配场景,比如:
struct A { A() {} A(const A&) = delete; template<typename T> requires (!std::same_as<std::remove_cvref_t<T>, A>) A(T&&) {} A& operator=(const A&) = delete; };
不过这样一来,这个泛型构造函数就不再接受A类型的参数了,你还是没法直接拷贝vector——因为这时候连构造A的途径都没了。本质上,如果你想让vector能被拷贝,元素类型必须满足可拷贝构造的要求,而你的A因为显式删除了拷贝构造函数,已经不符合这个要求了。
备注:内容来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

