正在删除第三方类的副本ctor



我有一个存储大型std::map的类。我的理解是,做这件事的惯用方法是:

class Foo {
public:
Foo(/* Note: passed by value */ std::map<Bar, Baz> large_map) : large_map_(std::move(large_map)) {}
private:
std::map<Bar, Baz> large_map_;
};
int main() {
std::map<Bar, Baz> large_map;
// Work hard to initialize large_map.
Foo foo = Foo(std::move(large_map));
}

这将large_map的所有权从main转移到构造函数arg,然后转移到Foo的成员。这个问题是代码很难正确使用,我发现有人在某个地方创建了一个Foo,却忘记了将映射移动到ctor:中

void deep_dark_hidden_code() {
std::map<Bar, Baz> large_map;
// Work hard to initialize large_map.
Foo foo = Foo(large_map); // Whoops! The author of this code forgot to std::move
}

我正在寻找一种写Foo的方法,以防止此类错误。我的第一个想法是使用unique_ptr

class Foo {
public:
Foo(std::unique_ptr<std::map<Bar, Baz>> large_map_ptr) : large_map_(std::move(*large_map_ptr)) {}
private:
std::map<Bar, Baz> large_map_;
};
int main() {
std::unique_ptr<std::map<Bar, Baz>> large_map_ptr = new std::map<Bar, Baz>;
// Work hard to initialize large_map_ptr.
Foo foo = Foo(std::move(large_map_ptr));
}

该代码本质上是使用unique_ptr作为破解来擦除std::map的复制构造函数。我的问题是,是否有更明确的方法来做到这一点。一些神奇的模板make_uncopyable,如:

class Foo {
public:
Foo(make_uncopyable<std::map<Bar, Baz>> large_map) : large_map_(std::move(large_map)) {}
private:
std::map<Bar, Baz> large_map_;
};

所需的效果是保持main中的代码不变,但阻止deep_dark_hidden_code中的代码编译。

这里的标题似乎有点用词不当(或者至少与您的问题内容不一致(:

(至少在给定的示例中(,您不希望删除复制构造函数,即Foo::Foo(const Foo& other),而是使用不可移动的参数来阻止调用Foo的构造函数。

正如Mestkon所指出的(这都归功于他们——如果他们想把它作为答案发布,只要喊我一声,我就会删除我的(,你可以更改Foo的构造函数,使其需要std::map<Bar, Baz>&& large_map,即

Foo(std::map<Bar, Baz>&& large_map) : large_map_(std::move(large_map)) {}

Godbolt的测试确认编译器将拒绝接受deep_dark_hidden_code().中的Foo foo = Foo(large_map);,要求参数是可移动的(根据需要(。这可能仍然会冒着其他人的风险;"固定";他们的代码通过简单地在他们的CCD_ 17周围拍打CCD_ 16。。。然后尝试在用它构建CCD_ 18之后继续使用它

如果您想要真的想要阻止调用复制构造函数(此处为std::map(,事情会变得相当困难,因为您无法更改定义std::map来擦除其复制构造函数。我觉得我没有一个好的答案。

最新更新