コンパイラ エラー C2280

'declaration': 削除された関数を参照しようとしています

deleted された関数を参照しようとしていることがコンパイラによって検出されました。 このエラーは、ソース コードで明示的に = deleted としてマークされているメンバー関数の呼び出しによって引き起こされることがあります。 コンパイラによって自動的に宣言され、deleted としてマークされた構造体またはクラスの暗黙的な特殊メンバー関数の呼び出しが原因で、このエラーが発生することもあります。 どのようなときに、default または deleted の特殊メンバー関数がコンパイラによって自動的に生成されるかの詳細については、「特殊なメンバー関数」を参照してください。

例: 明示的に削除された関数

明示的に deleted された関数を呼び出すと、このエラーが発生します。 明示的に deleted されたメンバー関数とは、それを使用できないようクラスまたは構造体が意図的に設計されていることを暗に意味します。そのため、この問題を解決するには、それを避けるようにコードを変更する必要があります。

// C2280_explicit.cpp
// compile with: cl /c /W4 C2280_explicit.cpp
struct A {
    A();
    A(int) = delete;
};

struct B {
    A a1;
    A a2 = A(3); // C2280, calls deleted A::A(int)
    // To fix, remove the call to A(int)
};

void f() {
    B b;    // calls implicit B::B(void)
}

例: 初期化されていないデータメンバー

参照型のデータ メンバーまたは const データ メンバーが初期化されていないと、deleted される既定のコンストラクターがコンパイラによって暗黙的に宣言されます。 この問題を解決するには、宣言されているデータ メンバーを初期化します。

// C2280_uninit.cpp
// compile with: cl /c C2280_uninit.cpp
struct A {
    const int i; // uninitialized const-qualified data
    // members or reference type data members cause
    // the implicit default constructor to be deleted.
    // To fix, initialize the value in the declaration:
    // const int i = 42;
} a;    // C2280

例: 参照型と const データ メンバー

const または参照型のデータ メンバーがあると、deleted されるコピー代入演算子がコンパイラによって宣言されます。 初期化後、これらのメンバーへの代入はできなくなるため、単純な copy や move は正しく機能しません。 この問題を解決するには、ロジックを変更して、エラーの原因となっている代入演算子を削除することをお勧めします。

// C2280_ref.cpp
// compile with: cl /c C2280_ref.cpp
extern int k;
struct A {
    A();
    int& ri = k; // a const or reference data member causes
    // implicit copy assignment operator to be deleted.
};

void f() {
    A a1, a2;
    // To fix, consider removing this assignment.
    a2 = a1;    // C2280
}

例: movable であるために暗黙的なコピーが削除される

クラスに移動コンストラクターまたは移動代入演算子が宣言されているにもかかわらず、コピー コンストラクターが明示的に宣言されていない場合、コピー コンストラクターがコンパイラによって暗黙的に宣言され、deleted として定義されます。 同様に、クラスに移動コンストラクターまたは移動代入演算子が宣言されているにもかかわらず、コピー代入演算子が明示的に宣言されていない場合、コピー代入演算子がコンパイラによって暗黙的に宣言され、deleted として定義されます。 この問題を解決するには、これらのメンバーを明示的に宣言する必要があります。

unique_ptr に関連してエラー C2280 が発生した場合、deleted された関数であるコピー コンストラクターを呼び出そうとしたことが原因となっている可能性が高いです。 仕様により、unique_ptr をコピーすることはできません。 代わりに移動コンストラクターを使用して所有権を移転してください。

// C2280_move.cpp
// compile with: cl /c C2280_move.cpp
class base
{
public:
    base();
    ~base();
    base(base&&);
    // Move constructor causes copy constructor to be
    // implicitly declared as deleted. To fix this
    // issue, you can explicitly declare a copy constructor:
    // base(base&);
    // If you want the compiler default version, do this:
    // base(base&) = default;
};

void copy(base *p)
{
    base b{*p};  // C2280
}

例: variant と volatile のメンバー

Visual Studio 2015 Update 2 より前のバージョンのコンパイラは標準に準拠しておらず、匿名共用体については既定のコンストラクターとデストラクターが生成されていました。 現在では、暗黙的に deleted として宣言されるようになっています。 また、これらのバージョンでは、volatile メンバー変数を含んだクラスや構造体において、default のコピー コンストラクターと移動コンストラクター、および default のコピー代入演算子と移動代入演算子の、標準に準拠しない暗黙的定義が許可されていました。 現在、これらは非 trivial なコンストラクターや代入演算子を含んでいると見なされるようになり、default の実装は生成されません。 そのようなクラスが共用体 (またはクラス内の匿名共用体) のメンバーである場合、共用体またはクラスのコピー コンストラクターと移動コンストラクター、およびコピー代入演算子と移動代入演算子は暗黙的に deleted として定義されます。 この問題を解決するには、必要な特殊メンバー関数を明示的に宣言する必要があります。

// C2280_variant.cpp
// compile with: cl /c C2280_variant.cpp
struct A {
    A() = default;
    A(const A&);
};

struct B {
    union {
        A a;
        int i;
    };
    // To fix this issue, declare the required
    // special member functions:
    // B();
    // B(const B& b);
};

int main() {
    B b1;
    B b2(b1);  // C2280
}

例: 間接的な基底メンバーは削除される

Visual Studio 2015 Update 2 より前のバージョンのコンパイラは標準に準拠しておらず、間接的に派生された private virtual 基底クラスの特殊メンバー関数を派生クラスから呼び出すことが許可されていました。 現在、そのような呼び出しに対しては、コンパイラ エラー C2280 が生成されるようになっています。

この例のクラス top は、private virtual base から間接的に派生しています。 標準に準拠しているコードでは、base のメンバーに top がアクセスすることはできず、top 型のオブジェクトは、既定で構築することも破棄することもできません。 古いコンパイラの動作に依存したコードでこの問題を解決するには、protected virtual の派生を使用するように中間クラスを変更するか、直接の派生を使用するように top クラスを変更します。

// C2280_indirect.cpp
// compile with: cl /c C2280_indirect.cpp
class base
{
protected:
    base();
    ~base();
};

class middle : private virtual base {};
// Possible fix: Replace line above with:
// class middle : protected virtual base {};
class top : public virtual middle {};    // C4594, C4624
// Another possible fix: use direct derivation:
// class top : public virtual middle, private virtual base {};

void destroy(top *p)
{
    delete p;  // C2280
}