How to initialize private static constant array of the same class C++

78 views Asked by At

I need to make class B to work with graph of related objects of class A. An instance of B contains A by value, and links to linked B objects(array indexes). Array of B must to be private as OOP principles dictate. I have long generated initialization list.

//What I want to do(not working)
header:
class A{};

class B{
    static const B array[24]={B(A(),0,0,0,0,0,0),//zeros are numbers
                            ...............//many rows
                            B(A(),0,0,0,0,0,0)};
    A a;
    char l[6];
public:
    B(A _a,char l1, char l2, char l3,char l4, char l5, char l6);
};
//attempt with initialization in cpp
header:
class A{};

class B{
    static const extern B array[24];
    A a;
    char l[6];
public:
    B(A _a,char l1, char l2, char l3,char l4, char l5, char l6);
};

cpp:
static const B::array={B(A(),0,0,0,0,0,0),//zeros are numbers
                       ...............//many rows
                       B(A(),0,0,0,0,0,0)};

I tried above and similar variants. Compiler says I can't use conflicting specifiers or incomplete types or that field was private. In the past instead of class I used namespace and it worked, but that way array is not encapsulated.

//global variable in namespace(works, but not private)
header:
class A{};

namespace NSB{
class B{
    A a;
    char l[6];
public:
    B(A _a,char l1, char l2, char l3,char l4, char l5, char l6);
};
const extern B array[24];
}

cpp:
const NSB array[24]={B(A(),0,0,0,0,0,0),//zeros are numbers
                    ...............//many rows
                    B(A(),0,0,0,0,0,0)};
}

I expect a way to make preinitialized private static array somehow.

2

There are 2 answers

5
Öö Tiib On BEST ANSWER

Unsure what you tried differently ... that seems to compile (and run):

class A{};

class B{
    static const B array[2];
    A a;
    char l[6];
public:
    B(A _a,char l1, char l2, char l3,char l4, char l5, char l6) {}
};

const B B::array[2]={B(A(),0,0,0,0,0,0), B(A(),0,0,0,0,0,0)};

int main() {} 
0
Pepijn Kramer On

The whole initialization can be moved to compile time using constexpr like this :

#include <array>
#include <iostream>

namespace your_namespace
{
    class A {};

    class B
    {
        A a;
        std::array<char, 6> l;

    public:
        // constexpr constructor for initialization
        // allows setup of B at compile time
        constexpr B(A&& _a, std::array<char, 6>&& values) :
            a{ _a },
            l{ values }
        {
        }

        constexpr const auto& values() const noexcept
        {
            return l;
        }
    };

    namespace details // named namespace for test, you can make it unnamed to hide it.
    {
        // the array of instances of B 
        // can be a compile time resource (no need to use static initialization)
        static constexpr std::array<B, 2> b_array
        { {
            {A{},{0,0,0,0,0,0}}, // constructor parameters for a B instance, the values are an array and need their own {}
            {A{},{1,1,1,1,1,1}}
        } };

        // this b_array cannot be a static constexpr member of B because
        // B must be a complete type first.
    }

} // namespace your_namespace

int main()
{
    for (const auto& b : your_namespace::details::b_array)
    {
        for (const auto& value : b.values())
        {
            std::cout << static_cast<int>(value) << " ";
        }
        std::cout << "\n";
    }

    return 0;
}