2

I am trying to write static initializers for this class:

class Cube3x3
{
    union CornerData
    {
        u8  mData8[8];
        u32 mData16[4];
        u32 mData32[2];
        u64 mData64;
    };

    union EdgeData
    {
        u8  mData8[12];
        u32 mData32[3];
    };

    CornerData mCorners;
    EdgeData mEdges;

    static const Cube3x3 sSolved;
};

I've tried this, and a lot of variants, and it seems like nothing I try will work.

const Cube3x3 Cube3x3::sSolved =
{
    { 0, 0, 1, 0, 0, 0, 1, 0 },
    { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }
};

Does anyone know how, or if, its possible to static initialize this?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
VoidStar
  • 5,241
  • 1
  • 31
  • 45

3 Answers3

1

If you are willing to change Cube3x3 from a class to a struct, you can use:

const Cube3x3 Cube3x3::sSolved = {0};

Update

When a struct is used, you can also initialize the members with non-zero values, like you have in the updated question.

const Cube3x3 Cube3x3::sSolved =
{
    { 0, 0, 1, 0, 0, 0, 1, 0 },
    { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0 }
};
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Sorry, I don't really want to zero it, I actually have tons of enum values that go in here that I didn't want to paste into the question. I'll try to clarify. – VoidStar Jun 16 '14 at 06:00
  • The code snippet you gave does not compile when Cube3x3 is a class or a struct, at least not on VS2013, which is why I posted the question. Is it my compiler that is at fault? – VoidStar Jun 16 '14 at 06:09
  • @VoidStar, that would be my guess. Checkout a working version at http://ideone.com/AWUc4v. – R Sahu Jun 16 '14 at 06:13
  • Okay I was making a mistake, it does work with struct in VS2013. That was the core mistake I was making, I thought class would behave identically to struct in terms of static initializer syntax, but this is evidently not the case. – VoidStar Jun 16 '14 at 06:29
  • ACTUALLY, class and struct DO both allow static initializer syntax! The real culprit is that apparently you cannot statically initialize a protected/private member variable! So you CAN use this syntax on classes as long as everything is public! – VoidStar Jun 16 '14 at 07:03
0

One solution is to use C++11 lambdas to initialize it.

const Cube3x3 Cube3x3::sSolved = []{
    Cube3x3 cube;
    std::fill(std::begin(cube.mCorners.mData8), std::end(cube.mCorners.mData8), 0);
    std::fill(std::begin(cube.mEdges.mData8), std::end(cube.mEdges.mData8), 0);

    return cube;
}();

Live Example

Note the () at the end, which indicates that we are calling that lambda function. If you are using a non-C++11 compiler, or at least one that doesn't yet support C++11 lambdas, you could write a function with basically the same body as you would have when writing a lambda. You then need to call that function when static-initializing the desired object.

Cube3x3 initialize() {
    Cube3x3 cube;
    std::fill(&cube.mCorners.mData8[0], &cube.mCorners.mData8[8], 0);
    std::fill(&cube.mEdges.mData8[0], &cube.mEdges.mData8[8], 0);

    return cube;
}


const Cube3x3 Cube3x3::sSolved = initialize();

Live Example

Mark Garcia
  • 17,424
  • 4
  • 58
  • 94
  • This is almost a nice workaround, but mCorners and mEdges are protected to Cube3x3, which pretty much rules out lambdas. I could go with the second version of your answer too I suppose, using a member friend or member function... I may have to do that for now. – VoidStar Jun 16 '14 at 06:16
0

The code is working for me if I add a constructor for your class that takes the CornerData and EdgeData as arguments.

Cube3x3(CornerData cornerData, EdgeData edgeData) 
                        : mCorners(cornerData), 
                          mEdges(edgeData)
{
}

Here is the link: http://ideone.com/XzBXZM

sajas
  • 1,599
  • 1
  • 17
  • 39