重用复制和交换习惯用法
我正在尝试将复制和交换习惯用法放入可重用的 mixin 中:
template<typename Derived>
struct copy_and_swap
{
Derived& operator=(Derived copy)
{
Derived* derived = static_cast<Derived*>(this);
derived->swap(copy);
return *derived;
}
};
我打算将其通过 CRTP 混合:
struct Foo : copy_and_swap<Foo>
{
Foo()
{
std::cout << "default\n";
}
Foo(const Foo& other)
{
std::cout << "copy\n";
}
void swap(Foo& other)
{
std::cout << "swap\n";
}
};
但是,一个简单的测试表明它不起作用:
Foo x;
Foo y;
x = y;
这只打印“默认”两次,也没有打印“打印“复制”或“交换”。我在这里缺少什么?
I'm trying to put the copy-and-swap idiom into a reusable mixin:
template<typename Derived>
struct copy_and_swap
{
Derived& operator=(Derived copy)
{
Derived* derived = static_cast<Derived*>(this);
derived->swap(copy);
return *derived;
}
};
I intend it to be mixed in via CRTP:
struct Foo : copy_and_swap<Foo>
{
Foo()
{
std::cout << "default\n";
}
Foo(const Foo& other)
{
std::cout << "copy\n";
}
void swap(Foo& other)
{
std::cout << "swap\n";
}
};
However, a simple test shows that it is not working:
Foo x;
Foo y;
x = y;
This only prints "default" twice, neither "copy" nor "swap" is printed. What am I missing here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这:
没有为基类声明复制赋值运算符(它有错误的签名)。因此
Foo
中默认生成的赋值运算符不会使用该运算符。记住12.8:
编辑 不要这样做(你能明白为什么吗?):
你可以这样做:但是你失去潜在的复制省略优化。事实上,这将分配两次派生类的成员:一次通过
copy_and_swap
赋值运算符,一次通过派生类生成的赋值运算符。要纠正这种情况,您必须执行以下操作(并且不要忘记):这个故事的寓意:不要为复制和交换惯用法编写 CRTP 类嗯>。
This:
doesn't declare a copy assignment operator for the base class (it has the wrong signature). So the default generated assignment operator in
Foo
will not use this operator.Remember 12.8:
EDIT don't do this (can you see why ?):
You can do:but you lose the potential copy elision optimization.Indeed, this would assign twice the members of derived classes: once via
copy_and_swap<Derived>
assignment operator, and once via the derived class' generated assignment operator. To correct the situation, you'd have to do (and not forget to do):The moral of the story: don't write a CRTP class for the copy and swap idiom.
如果内存正确的话,您不能将赋值运算符作为特殊情况继承。我相信如果您需要的话,可以显式
使用
它们。另外,要小心过度使用复制和交换。它会产生非理想的结果,其中原始文件具有可以重复使用来制作副本的资源,例如容器。安全性得到保证,但最佳性能却没有得到保证。
You cannot inherit assignment operators as a special case, if memory correctly serves. I believe that they can be explicitly
using
'd in if you need.Also, be careful about over use of copy-and-swap. It produces non-ideal results where the original has resources that could be re-used to make the copy, such as containers. Safety is guaranteed but optimum performance is not.
恐怕这是需要宏的一个领域,因为自动生成的复制和赋值运算符的规则很复杂。
无论您做什么,您都会遇到以下两种情况之一:
因此,下一个问题是:自动化这样的写入是否值得?
复制和交换仅用于非常特定的类。我认为这不值得。
I am afraid this is one area where a macro is necessary, because of the complex rules about automatically generated copy and assignment operators.
No matter what you do, you are in either of two cases:
The next question, therefore, is: Is it worth it to automate such writing ?
Copy-And-Swap is only used for very specific classes. I do not think it's worth it.
编译器自动为 Foo 生成一个复制赋值运算符,因为没有。
如果将 a 添加
到 Foo,您将看到一个错误,告诉您 g++ 上的歧义。
The compiler automatically generates a copy assignment operator for Foo, since there is none.
If you add a
to Foo you will see an error telling you about the ambiguity on g++.
也许您可以重写它,使其看起来像这样:
它可能全部被内联,并且可能不会比原始代码慢。
Maybe you could rewrite it so it looks like so:
It'll probably all get inlined and likely won't be any slower than the original code.
这并没有真正回答问题(@Alexandre C. 已经这样做了),但是如果你反转继承,你可以让它工作:
This does not really answer the question (@Alexandre C. already did), but if you reverse the inheritance, you could make it work: