Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
378 views
in Technique[技术] by (71.8m points)

c++ - Initialization of member array of non-copyable, non-movable, explicitly constructed types

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

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

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.

What doesn't work:

  • 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.

Edit: Updated info about member array requirement.

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

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.

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.

Just for the sake knowing how to I'd still like to see potential solutions to the original problem though.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
struct Foo {
  A a[2];
}

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.

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

};

Then declare Foo:

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

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


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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...