Why deleted copy constructor doesn't let to use other constructor with polymorphic type?

随声附和 提交于 2019-12-10 17:38:27

问题


I wonder why this program doesn't compile (the same behavior on msvc, gcc and clang):

#include <iostream>

using namespace std;

struct Action
{
    virtual void action()
    {
        cout << "Action::action()\n";
    }
};

struct ActionDecorator : Action
{
    ActionDecorator(const ActionDecorator&) = delete;
    ActionDecorator(Action & action) : origAction(action)
    {
    }

    void action() override
    {
        decoration();
        origAction.action();
    }

private:
    void decoration()
    {
        cout << "ActionDecorator::decoration()\n";
    }

    Action & origAction;
};

int main()
{
    Action action;
    ActionDecorator actionDecorator(action);
    ActionDecorator actionDecorator2(actionDecorator);
    actionDecorator2.action();
}

According to my expectation, deleted copy constructor should let construct ActionDecorator by other ActionDecorator instance, as it is polymorphic type of Action. Instead I have to explicit cast ActionDecorator instance to Action& as compiler complains about attempting to reference a deleted copy constructor. Is there some standard rule which explains such behavior?


回答1:


Deleting a a function doesn't remove it from overload resolution. The function is merely defined as deleted. The purpose is to make the program ill-formed when overload resolution chooses that function.

Since the copy c'tor is a better match than the special base class c'tor you provided, overload resolution will always pick it if you don't cast.

How to best handle it is debatable. You could theoretically have the copy c'tor do a similar sort of wrapping. I'm torn about having a copy c'tor that doesn't copy, however. Your millage may very.

Another option, which I'm personally much more comfortable with, is to not provide public constructors as is. Instead, have clients create decorators via a regular named function. Something like this:

ActionDecorator decorate(Action& action) {
  return {action};
}

Now the class can truly remain non-copyable, and clients will never need to cast it themselves. If they pass an ActionDecorator to decorate, it will bind to an Action reference prior to constructing the instance. So it won't even consider the copy c'tor.

The class will have to be movable, for this to work prior to C++17, however.



来源:https://stackoverflow.com/questions/49173654/why-deleted-copy-constructor-doesnt-let-to-use-other-constructor-with-polymorph

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!