11

コピーアンドスワップのイディオムを再利用可能なミックスインに入れようとしています:

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;

これは「デフォルト」を 2 回出力するだけで、「コピー」も「スワップ」も出力されません。ここで何が欠けていますか?

4

6 に答える 6

0

自動生成されたコピーおよび代入演算子に関する複雑なルールのため、これはマクロが必要な領域の 1 つです。

何をするにしても、次の 2 つのケースのいずれかになります。

  • 代入演算子の宣言を (明示的に) 提供しました。この場合、定義も提供する必要があります。
  • 代入演算子の宣言を (明示的に) 提供していません。この場合、基本クラス非静的メンバーに利用可能なものがある場合、コンパイラはそれを生成します。

したがって、次の質問は次のとおりです。そのような書き込みを自動化する価値はありますか?

Copy-And-Swap は、非常に特定のクラスにのみ使用されます。私はそれが価値があるとは思わない。

于 2011-08-16T15:50:24.610 に答える
0

たぶん、次のように書き直すことができます。

template<class Derived>
struct CopySwap
{
  Dervied &operator=(Derived const &other)
  {
    return AssignImpl(other);
  }

  Derived &operator=(Dervied &&other)
  {
    return AssignImpl(std::move(other));
  }

private:
  Derived &AssignImpl(Derived other)
  {
    auto self(static_cast<Derived*>(this));
    self->swap(other);
    return *self;
  }
};

おそらくすべてインライン化され、元のコードよりも遅くなることはありません。

于 2011-08-16T15:12:57.127 に答える
0

これは実際には質問に答えません(@Alexandre C. はすでに答えました)が、継承を逆にすると、それを機能させることができます:

template<typename Base>
struct copy_and_swap : Base
{
    copy_and_swap& operator=(copy_and_swap copy)
    {
        swap(copy);
        return *this;
    }
};

struct Foo_
{
    Foo_()
    {
        std::cout << "default\n";
    }

    Foo_(const Foo_& other)
    {
        std::cout << "copy\n";
    }

    void swap(Foo_& other)
    {
        std::cout << "swap\n";
    }
};

typedef copy_and_swap<Foo_> Foo;

int main()
{
    Foo x;
    Foo y;
    x = y;
}
于 2011-08-16T15:56:06.827 に答える