3

自明ではないクラスのメンバー配列を含むクラスを作成して初期化しようとしています。これには、いくつかの状態と (いくつかのコーナーの周り) が含まれていますstd::atomic_flag。C++11 以降では、メンバー配列を初期化できるはずです。

コードは (最小限に) 次のようになります。

class spinlock
{
    std::atomic_flag flag;
    bool try_lock() { return !flag.test_and_set(std::memory_order_acquire); }
public:
    spinlock() : flag(ATOMIC_FLAG_INIT){};
    void lock()     { while(!try_lock()) ; }
    void unlock()   { flag.clear(std::memory_order_release); }
};

class foo
{
    spinlock lock;
    unsigned int state;
public:
    foo(unsigned int in) : state(in) {}
};

class bar
{
    foo x[4] = {1,2,3,4}; // want each foo to have different state
public:
    //...
};

コンパイラの出力を正しく理解している場合、これはメンバー配列を構築するのではなく、一時を構築し、移動/コピー コンストラクターを呼び出して、サブクラスで移動コンストラクターを呼び出しますstd::atomic_flag。私が得たコンパイラ出力(gcc 4.8.1)は次のとおりです。

[...] error: use of deleted function 'foo::foo(foo&&)'
note: 'foo::foo(foo&&)' is implicitly deleted because the default definition would be ill-formed
error: use of deleted function 'spinlock::spinlock(spinlock&&)'
note: 'spinlock::spinlock(spinlock&&)' is implicitly deleted because [...]
error: use of deleted function 'std::atomic_flag::atomic_flag(const std::atomic_flag&)'
In file included from [...]/i686-w64-mingw32/4.8.1/include/c++/atomic:41:0
[etc]

配列を削除し、代わりに単一のfooメンバーを内部barに配置すると、標準のコンストラクター初期化子を使用するか、新しい宣言内初期化を使用して適切に初期化できますが、まったく問題ありません。メンバー配列で同じことを行うと、何を試しても上記のエラーで失敗します。

配列要素が明らかに一時的に構築され、直接構築されるのではなく移動されることはあまり気にしませんが、コンパイルされないという事実は明らかにショーストッパーです。

配列要素を強制的に構築する (移動しない) ようにする方法、またはこれを回避する方法はありますか?

4

2 に答える 2

1

Gcc は、バージョン 10.2 までの仮想デストラクタを使用して、オブジェクトの配列のリスト初期化をコンパイルすることを拒否します。10.3 で修正されました。たとえばnoncopyable、@dyp の回答に仮想デストラクタが含まれていた場合、gcc は次の行のコンパイルに失敗します。

noncopyable f0[] = {{1}, {2}, {3}, {4}}; 

削除されたコピーと移動 c-rs を主張します。ただし、10.3 以降では正常にコンパイルされます。

于 2021-07-26T08:26:01.183 に答える