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

static initialization order fiasco
c++ static initialization order
c member initialization

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.

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.

c++, is valid because the outer {} are for the std::array struct object and the inner {} are associates pieces of an initializer-list to subobjects (non-static data members of a obj_array has one subobject, of type Object[2] . Initialization of member array of non-copyable, non-movable, explicitly constructed types. The most logical way to structure them is by putting them in an array. E.g. something like : 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

The short answer - no. The longer answer - kind of, but its disgusting.

Take a look at this discussion.

Why you can't list-initialize containers of non-copyable types – C++ , Why you can't list-initialize containers of non-copyable types and the std::​initializer_list<E> object is constructed to refer to that array. Each element of that array is copy-initialized with the corresponding element of the initializer list, and thestd::initializer_list<E> object is constructed to refer to that array. So the initializer_list can be thought of as just a wrapper for a temporary array we initialize with the elements in the braced-init-list.

I am able to solve the problem as follows (also using SystemC, here my non-copyable, non-movable items are 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"}}}
    {}
};

Constructors, C++ FAQ, Which constructor gets called when I create an array of Fred objects? This question covers the C++11 feature of constructors that call same-type constructors. Watch this space for discussion of Non Static Data Member Initialization in C++11 constructed directly inside x_ — the compiler does not make a separate copy  Created attachment 46733 Output of "gcc -v" and the compilation error This bug report is based on the stackoverflow discussion that can be found here: https

Making a noncopyable but movable class, descriptor_owner construct_descriptor() { return descriptor_owner("Construct using descriptor_owner1() : descriptor_(NULL) {} explicit descriptor_owner1(​const According to the documentation, to write a movable but noncopyable type in We do NOT have rvalues #include <boost/container/vector.hpp> namespace  How to declare and initialize array in a class? I'm having a problem with a program I'm writing for the mbed. I'm trying to create a class that contains an (const) array that contains integers. The declaration of the array happens in the .h file:

C++ Dos and Don'ts, Dynamic initialization of function-scope static variables is thread-safe in For a non-copyable/movable type, delete the copy operations (the move when construction performs significant logic, uses an explicit constructor, or in If possible, initialize class members in their declarations, except where a member's value is  std::array is a container that encapsulates fixed size arrays. This container is an aggregate type with the same semantics as a struct holding a C-style array T [N] as its only non-static data member. Unlike a C-style array, it doesn't decay to T * automatically.

Initialization of member array objects avoiding move constructor, This slight difference also manifests in the array case: noncopyable f0[] = {{1}, {2}, copy-initialization from a braced-init-list may not use an explicit constructor. Explicit copy-constructor. It is worthwhile to note that C++ allows one more way to control copy-construction. An explicit copy-constructor will prevent the compiler from calling a copy-constructor implicitly. I.e., passing an object by value and returning an object by value will be disabled for the class having an explicit copy-constructor.

Comments
  • Why not just write a loop that allocates each A on the stack and initializes each value?
  • One has to ask why you have set all these restrictions on your code.
  • @vincent I just updated my question. Short story: creating the As on the stack is not allowed. Long story: the code is used in a "debugger"-like tool written by an external company and this tool can't handle inspection of pointer members.
  • @NeilButterworth Thrust me, I'm not putting these restriction on the code because I want to. The restrictions are entirely due to external libraries and (very expensive) tools.
  • Would it be an option to derive B from A and construct array of Bs? class B : public A { public: B(int value): A(value) {} }; B b[] = {1, 2, 3};
  • Neat. I'm afraid the tool won't support it, but it's worth a try.
  • +1: nice answer. I think the As in operator[] should actually be Ts though. Also, is there a way to make this work with types whose constructor takes more than one argument?