16

と仲良くしようとしていstd::functionます。ここの参照から、std::functionの ctorへの引数は呼び出し可能であり、コピー構築可能でなければならないことがわかります。だからここに小さな例があります:

#include <iostream>
#include <type_traits>
#include <functional>

class A {
public:
    A(int a = 0): a_(a) {}
    A(const A& rhs): a_(rhs.a_) {}
    A(A&& rhs) = delete;
    void operator() ()
    {
        std::cout << a_ << std::endl;
    }

private:
    int a_;
};

typedef std::function<void()> Function;

int main(int argc, char *argv[])
{
    std::cout << std::boolalpha;
    std::cout << "Copy constructible: "
              << std::is_copy_constructible<A>::value << std::endl;
    std::cout << "Move constructible: "
              << std::is_move_constructible<A>::value << std::endl;
    //Function f = A();
    return 0;
}

呼び出し可能でコピー構築可能ですが、移動構築可能クラスはありません。でラップするにはこれで十分だと思いますFunction。しかし、コメント行のコメントを外すと、コンパイラは削除された移動コンストラクターについて非常に動揺します。ここにアイデアリンクがあります。GCC 4.8.0 もこれをコンパイルしません。

それで、それは私が誤解しているものですか、std::functionそれともGCCの間違った動作ですか?

4

2 に答える 2

11

GCC と Clang は正しいです。

§17.6.3.1.1テンプレート引数の要件 [utility.arg.requirements]

表 20MoveConstructible 要件 [moveconstructible].

  • T u = rv; u は構築前の rv の値に相当します。
  • T(rv); T(rv) は構築前の rv の値に相当します。

表 21CopyConstructible 要件 ( MoveConstructibleに加えて) [copyconstructible].

  • T u = v; v の値は変更されず、u と同等です。
  • テレビ); v の値は変更されず、T(v) と同等です。

次の点に注意してください。

CopyConstructible 要件 ( MoveConstructibleに加えて)

つまり、何かが CopyConstructible である場合、それはMoveConstructibleでなければなりませ。移動をコピーとして実装しても問題ありませんが。

アップデート:

C++11標準がCopyConstructibleis_copy_constructibleに関して定義していないように見えることは興味深いと思いますが、つまり、それらはまったく同じではなく、必要なものだけが必要なため、より緩和されています。is_copy_constructible

§20.9.4.3型プロパティ [meta.unary.prop]

表 49 — 型プロパティの述語

  • is_copy_constructible<T>; is_constructible<T,const T&>::value は true です。
于 2013-07-25T07:51:49.450 に答える
4

削除指定の目的を誤解しています。move-constructor はデフォルトで実装されていません。move-ctor なしでオブジェクトを移動しようとすると、コピーされるだけです。move-constructor を削除済みとして指定すると、それを呼び出して削除されたことを確認しようとします。つまり、一時オブジェクトをコピーすることはできません。move-constructor ステートメントを削除すると、機能します。

編集 - 明確化:

move-constructor が宣言されていない場合 (ここで =delete は宣言です)、一時オブジェクトからの構築は (const 参照から) copy-constructor を呼び出します。移動コンストラクターを宣言すると、一時オブジェクトからの構築がこれを呼び出そうとします。したがって、move-ctor の削除を宣言すると、delete 関数を呼び出そうとするため、エラーが発生します。宣言しないと、コピー ctor が呼び出されます。

そのため、 std::function を宣言しなかった場合、あなたの例は機能しません.copy-ctorを使用するだけです。

デフォルトでは、copy-またはdefault-ctorで発生するように、宣言されていない場合は実装されます。

于 2013-07-25T07:52:51.683 に答える