初始化不可复制,不可移动,显式构造的类型

时间:2017-02-26 20:22:00

标签: c++ c++11

我无法修改的库类型如下:

class A {
  public:
    A () : A(0) { }
    explicit A (int const value) : value_(value) { }

    A (A const &) = delete;
    A (A &&) = delete;

    A & operator= (A const &) = delete;
    A & operator= (A &&) = delete;

  private:  
    int value_;
}

现在,我有一个类,需要一堆A个成员。由于环境的其他限制,我在所有这些A中工作必须是单独的成员或成员数组(即我不能使用std::vector来放置它们in或创建指向它们的指针)。即我的课程归结为:

struct Foo {
  A a[2];
}

有没有办法用不同的初始值初始化每个成员?我一直在尝试使用支持列表初始化的各种形式,但由于A(int)显式或A没有复制/移动构造函数,它们都会失败。

什么不起作用:

  • Foo () : A{ { 1 }, { 2 } } { }:因为它是A(int)而无法致电explicit
  • Foo () : A{ { A(1) }, { A(2) } } { }:无法复制或移动分配。

修改:更新了有关成员数组要求的信息。

编辑2 :相关的库是SystemC。我的示例类A是一个端口(例如sc_core::sc_in)。

我不能使用指针数组的原因是,据我所知,Mentor Graphic's Questa无法真正处理它们。它将正确模拟模型,但不允许检查端口。即它无法在波形窗口中随时间绘制端口的值。我很可能在这方面被证明是错误的,因为这样可以解决我的问题。

编辑3:显然,在较新版本的Questa中,这是一个大问题。我不确定在看到这个问题和现在之间发生了什么变化,也可能是对开发环境的改变(这也是我无法控制的)。在任何情况下,我的Questa现在会自动在其变量名后面命名端口(除非在构造时明确重命名),所以一切都很好。

只是为了了解我如何仍然希望看到原始问题的潜在解决方案。

3 个答案:

答案 0 :(得分:1)

struct Foo {
  A a[2];
}
     

有没有办法用不同的首字母初始化每个成员   值?我一直在尝试使用braced-list的各种形式   初始化,但它们都因A(int)而失败   显式或A没有复制/移动构造函数。

您可能需要使用 placement-new 在某个原始存储阵列中创建A数组。然后,您可以创建构建每个std::initializer_list<ARGUMENT>所需的ARGUMENT A。类似的东西:

template<typename T, std::size_t Size, std::size_t Alignment = alignof(T)>
struct FixedArray{
    std::aligned_storage_t<sizeof(T), Alignment> data[Size];

    static constexpr std::size_t size = Size;

    template<typename U>
    FixedArray(std::initializer_list<U> ls){
        assert(ls.size() <= Size && "Invalid Size"); int index = 0;
        for(auto& x : ls)
            new (&data[index++]) T(x);
    }

    FixedArray(const FixedArray&) = delete;
    FixedArray(FixedArray&&) = delete;

    A& operator[](std::size_t index){
        auto ptr = reinterpret_cast<A*>(&data) + index;
        return *std::launder(ptr);            //Sort of a legal way to alias memory C++17
    }

    ~FixedArray(){
        for(std::size_t i = 0; i < size; i++)
            this->operator[](i).~T();
    }

};

然后宣布Foo:

struct Foo {
    FixedArray<A, 4> a;
};

使用FooA(546)A(99)A(-4)创建A(0)

int main() {
    Foo f{{546, 99, -4, 0}};
    return 0;
}

查看有效的Demo

-O3优化级别使用GCC 6.3进行测试后,使用FixedArray与普通原始数组生成完全相同的程序集,请参阅gcc.godbolt.com

答案 1 :(得分:0)

简短的回答 - 没有。更长的答案 - 有点,但令人作呕。

查看this讨论。

答案 2 :(得分:0)

我能够解决以下问题(也使用SystemC,这里的不可复制,不可移动的项目是sc_modules):

class Object : sc_module {
    Object(sc_module_name name){}
};

class Container : sc_module {

    std::array<Object, 3> objects;

    Container(sc_module_name name) :
    objects{{{"object1"},{"object2"},{"object3"}}}
    {}
};