8

Although I much enjoy the new features in C++11, sometimes I feel like I'm missing some of its subtleties.

Initializing the int array works fine, initializing the Element2 vector works fine, but initializing the Element2 array fails. I think the correct syntax should be the uncommented line, but none of the initialization attempts have succeeded for me.

#include <array>
#include <vector>

class Element2
{
    public:
            Element2(unsigned int Input) {}
            Element2(Element2 const &Other) {}
};

class Test
{
    public:
            Test(void) :
                    Array{{4, 5, 6}},
                    Array2{4, 5},
                    //Array3{4, 5, 6}
                    Array3{{4, 5, 6}}
                    //Array3{{4}, {5}, {6}}
                    //Array3{{{4}, {5}, {6}}}
                    //Array3{Element2{4}, Element2{5}, Element2{6}}
                    //Array3{{Element2{4}, Element2{5}, Element2{6}}}
                    //Array3{{{Element2{4}}, {Element2{5}}, {Element2{6}}}}
                    {}
    private:
            std::array<int, 3> Array;
            std::vector<Element2> Array2;
            std::array<Element2, 3> Array3;
};

int main(int argc, char **argv)
{
    Test();
    return 0;
}

I've tried this on g++ 4.6.1 and 4.6.2 under MinGW.

How should I correctly go about initializing this array? Is it possible?

1
  • I guess this doesn't have much to do with initialization lists. Would it be appropriate to edit the question to make it more to-the-point? Commented Feb 5, 2012 at 3:57

1 Answer 1

7

The correct way to go about this is Array{{4, 5, 6}}. You cannot omit braces when you initialize a member with aggregate initialization. The only time you can omit braces is in a declaration of the form

T t = { ... }

So in your case you have to type out all braces: One for the std::array itself, and one for the int array. For Array3, your syntax is correct too, since int can be converted to Element2 implicitly.

From the remaining commented ones, the Array3{{{4}, {5}, {6}}}, Array3{{Element2{4}, Element2{5}, Element2{6}}} and Array3{{{Element2{4}}, {Element2{5}}, {Element2{6}}}} work too, but are more wordy. However conceptionally the Array3{{{4}, {5}, {6}}} one produces the least amount of temporaries on implementations that don't do copy elision (I guess that's irrelevant, but still good to know), even less than the Array3{{4, 5, 6}} one, because instead of copy initialization you use copy list initialization for your Element2, which doesn't produce an intermediary temporary by design.

Sign up to request clarification or add additional context in comments.

5 Comments

Are you saying that it should work fine and GCC is broken? Because the OP is saying that all of these variations fail. Also, how does this actually work, since std::array<Element2> is not an aggregate? I can cite the spec for requirements on aggregates, and std::array<Element2> fails that test. Can you cite the spec on how a non-aggregate can be initialized via aggregate initialization? I'm not saying you're wrong. I freely admit that I've never fully read the C++11 specification. At the same time, I would like some evidence to the veracity of your claim.
@NicolBolas As I understand it, std::array<T> is an aggregate: it is a struct without a user-defined constructor -- and it is explicitly mentioned as an aggregate in the description of <array>.
I read back through the requirements for an aggregate, and conspicuously absent were any requirements that the members of the aggregate not have user-provided constructors. So you're right.
@Ben thanks, not sure why i wrote "emit". Too much Qt programming.
The code works for me in g++ 4.7, using a snapshot from December.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.