簡體   English   中英

Constexpr初始化不可復制對象數組?

[英]Constexpr initialization of an array of non-copyable objects?

我想有一個B類,它具有另一個A類的3個成員對象。 AB構造函數都是constexpr B包含的A是不可復制且不可移動的。 這段代碼正確構建:

class A
{
public:
    constexpr explicit A(int a) {}
    A(const A&) = delete;
    A(A&&) = delete;
};

class B
{
public:
    constexpr B() :
            a0{0},
            a1{1},
            a2{2}
    {}
private:
    A a0;
    A a1;
    A a2;
};

int main()
{
    B b;
}

但是我真的很想將A類型的3個對象作為一個數組。 如果我嘗試這樣的簡單方法:

class A
{
public:
    constexpr explicit A(int a) {}
    A(const A&) = delete;
    A(A&&) = delete;
};

class B
{
public:
    constexpr B() :
            a{A{1}, A{2}, A{3}}
    {}
private:
    A a[3];
};

int main()
{
    B b;
}

無法建立:

$ g++ a.cpp 
a.cpp: In constructor ‘constexpr B::B()’:
a.cpp:21:22: error: use of deleted function ‘A::A(A&&)’
    a{A{1}, A{2}, A{3}}
                      ^
a.cpp:13:2: note: declared here
  A(A&&) = delete;
  ^
a.cpp:21:22: error: use of deleted function ‘A::A(A&&)’
    a{A{1}, A{2}, A{3}}
                      ^
a.cpp:13:2: note: declared here
  A(A&&) = delete;
  ^
a.cpp:21:22: error: use of deleted function ‘A::A(A&&)’
    a{A{1}, A{2}, A{3}}
                      ^
a.cpp:13:2: note: declared here
  A(A&&) = delete;
  ^
a.cpp:28:2: error: member ‘B::a’ must be initialized by mem-initializer in ‘constexpr’ constructor
  }
  ^
a.cpp:32:7: note: declared here
  A a[3];
       ^

移動A就可以解決嗎?

編輯:

正如@rustyx所建議的那樣,我對代碼進行了一些更改,它對於C ++ 11和C ++ 17(帶有explicit )可以正常工作。 但是,像往常一樣,實際代碼要復雜一些。 假設A 實際上是不可移動且不可復制的,說它有一個析構函數。

class A
{
public:
    constexpr explicit A(int a) {}
    ~A() {}
    A(const A&) = delete;
    A(A&&) = delete;
};

class B
{
public:
    constexpr B() :
            a{A{1}, A{2}, A{3}}
    {}
private:
    A a[3];
};

int main()
{
    B b;
}

即使使用C ++ 17,此操作也會失敗:

g++ a.cpp -std=c++17
a.cpp: In constructor ‘constexpr B::B()’:
a.cpp:14:22: error: use of deleted function ‘A::A(A&&)’
    a{A{1}, A{2}, A{3}}
                      ^
a.cpp:7:2: note: declared here
  A(A&&) = delete;
  ^
a.cpp:14:22: error: non-constant array initialization
    a{A{1}, A{2}, A{3}}
                      ^
a.cpp:15:3: error: use of deleted function ‘A::A(A&&)’
  {}
   ^
a.cpp:7:2: note: declared here
  A(A&&) = delete;
  ^

如果A的構造函數不是explicit它也會失敗。 如果我刪除析構函數,那么它可以工作,但是如果析構函數必須在那里,該怎么辦? 是否有解決此特定數組初始化問題的方法,或者我在這里不走運?

嚴格來說,從A{1}初始化A的實例是復制 (或移動)初始化。 大多數編譯器會忽略復制/移動構造函數,甚至不必費心調用復制/移動構造函數,但實際上僅從C ++ 17開始,就不需要復制/移動構造函數。

解決方法是,可以從A的構造函數中刪除explicitA就地構造A

class A
{
public:
    constexpr A(int a) {}
    A(const A&) = delete;
    A(A&&) = delete;
};

class B
{
public:
    constexpr B() :
            a{{1}, {2}, {3}}
    {}
private:
    A a[3];
};

int main()
{
    B b;
}

===編輯=== (針對問題編輯)

假設A實際上是不可移動且不可復制的,說它有一個析構函數。

我能想到的唯一可能的解決方法是新的核選擇

#include <memory>
#include <type_traits>
class A
{
public:
    constexpr A(int a) {}
    A(const A&) = delete;
    A(A&&) = delete;
    ~A() {}
};

class B
{
public:
    B() {
        new (std::addressof(a[0])) A(1);
        new (std::addressof(a[1])) A(2);
        new (std::addressof(a[2])) A(3);
    }
    A& getA(size_t offset) { return reinterpret_cast<A*>(a)[offset]; }
private:
    std::aligned_storage<sizeof(A), alignof(A)>::type a[3];
};

int main()
{
    B b;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM