初始化不可复制,不可移动,显式构造的类型的成员数组 [英] Initialization of member array of non-copyable, non-movable, explicitly constructed types

查看:87
本文介绍了初始化不可复制,不可移动,显式构造的类型的成员数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法修改的库具有类似于以下类型:

A library which I can't modify has a type akin to the following:

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 s作为成员。由于环境的其他限制,我在所有这些 A 中都必须是单独的成员或成员数组(即,我不能使用 std :: vector 放置它们或创建指向它们的指针)。即我的课程可以归结为:

Now, I have a class which requires a bunch of As as members. Due to other restrictions of the environment I'm working in all of these As must either be separate members or a member array (i.e. I can't use an std::vector to put them in or create pointers to them). I.e. my class boils down to this:

struct Foo {
  A a[2];
}

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

Is there any way to initialize each member with a distinct initial value? I've been trying various forms of using braced-list initialization, but they all fail due to either A(int) being explicit or A not having a copy/move-constructor.

不起作用的地方:


  • Foo():A {{1},{2}} {} :不会调用 A(int ),因为它是显式

  • Foo():A {{A (1)},{A(2)}} {} :不能复制或移动分配。

  • Foo () : A{ { 1 }, { 2 } } { }: won't call A(int) since it's explicit.
  • Foo () : A{ { A(1) }, { A(2) } } { }: can't copy- nor move-assign.

编辑::有关成员数组要求的更新信息。

Updated info about member array requirement.

编辑2:有问题的库是 SystemC 。我的示例类 A 是端口(例如 sc_core :: sc_in )。

Edit 2: The library in question is SystemC. My example class A is a port (e.g. sc_core::sc_in).

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

The reason I can't use an array of pointers is because, as far as I know, Mentor Graphic's Questa can't really deal with them. It will simulate the model correctly, but won't allow inspection of the ports. I.e. it won't be able to plot the port's values over time in a wave window. I would be very happen to be proven wrong about this, because that would allow a trivial solution to my problem.

编辑3:在新版本的Questa中不再是一个大问题。我不确定从看到此问题到现在之间有什么变化,也可能是开发环境的变化(这也是我无法控制的)。无论如何,我的Questa现在会自动以其变量名命名端口(除非在构造时被明确重命名),所以一切都很好。

Edit 3: Apparently this is a big issue anymore in a newer version of Questa. I'm not sure what changed between seeing this problem and now, could be a change to the development environment as well (which is also out of my control). In any case, my Questa now automatically names ports after their variable name (unless explicitly renamed at construction), so all is well.

只是为了知道如何

推荐答案


struct Foo {
  A a[2];
}

有没有办法用不同的初始
初始化每个成员值?我一直在尝试各种形式的使用括号列表
初始化的方法,但是由于 A(int)是显式的
A 没有复制/移动构造函数。

Is there any way to initialize each member with a distinct initial value? I've been trying various forms of using braced-list initialization, but they all fail due to either A(int) being explicit or A not having a copy/move-constructor.

您可能需要使用 placement-new 在一些原始存储阵列中创建一个 A 数组。然后,在每个构造 ARGUMENT 中创建一个 std :: initializer_list< ARGUMENT> > A 。像这样的东西:

You may need to use placement-new to create an array of A in some raw storage array. You then create a std::initializer_list<ARGUMENT> of the ARGUMENTs needed to construct each A. Something like:

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;
};

要创建具有<$ c $的 Foo c> A(546), A(99) A(-4) A(0)

To create Foo having A(546), A(99), A(-4), A(0):

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

查看正在工作的 演示

See a working Demo

在优化级别为 -O3 的GCC 6.3中进行测试后,使用 FixedArray 生成的组件几乎完全相同。与普通原始数组相比,请参见 gcc.godbolt.com

After testing with GCC 6.3 at -O3 optimization levels, about exactly the same assembly is generated for using FixedArray vs plain raw arrays, See it on gcc.godbolt.com.

这篇关于初始化不可复制,不可移动,显式构造的类型的成员数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆