2

I have a static array in a class and an enum for the index of such array.

enum  MyEnum
{
   FIRST = 0,
   SECOND,
   LAST
}

class MyClass
{
public:
    static string names[LAST];
    
}

I'd like to initialize my static array to associate a value of the array to each enum type like this:

names[FIRST] = "First";
names[SECOND] = "Second";

I know that I can initialize the array upon declaration like this static string names[] = {"First", "Second"}, but I want to explicitly assign the value to the corresponding enum to avoid errors.

In Java, there's a static block where you can do this kind of initialization, but I don't think that this is the case in C++. Is there an elegant way of doing this? I can't use std on my project, so the solution has to avoid any library usage.

Thanks in advance.

Kuri
  • 109
  • 1
  • 8
  • Get in line for *designated initializers* in C++... – Sergey Kolesnik Dec 03 '21 at 01:17
  • 2
    Anyway, from the description of your problem it seems that you are better off with `std::map` or `std::unordered_map`. This would be cleaner and less convoluted since you are assigning those pairs by hand anyway – Sergey Kolesnik Dec 03 '21 at 01:22
  • 2
    `I can't use std on my project, so the solution has to avoid any library usage.` Sure. What is `string`? – KamilCuk Dec 03 '21 at 01:28
  • *You can't decrease the chance of making errors.* Sure you can. But this poor sucker's not allowed to use most of the Standard ways. – user4581301 Dec 03 '21 at 01:32
  • @user4581301 Show me how you could decrease the change of making errors. – Yves Dec 03 '21 at 01:50
  • @user4581301 Let's say we can code like this: `names[FIRST] = MyEnum.at(0); names[SECOND] = MyEnum.at(1);`. So you are saying, that typing `MyEnum.at(0)` has a lower chance of making error than typing `"First"`? – Yves Dec 03 '21 at 01:57

2 Answers2

1

Write a function to initialize it. Function can't return an array - if you want to use an array, return a whole object that has an array inside it. Or you can return something dynamically allocated, a map or a vector.

#include <array>
#include <string>

enum  MyEnum {
    FIRST = 0,
    SECOND,
    LAST
};

std::array<std::string, LAST> construct_names() {
    std::array<std::string, LAST> r;
    r[FIRST] = "first";
    r[SECOND] = "second";
    return r;
}

static auto names = construct_names();

I can't use std on my project, so the solution has to avoid any library usage.

Roll your own types.

enum  MyEnum {
    FIRST = 0,
    SECOND,
    LAST
};

template<typename T, unsigned N>
struct MyArray {
    T data[N];
    T &operator[](unsigned i) {
        return data[i];
    }
};

MyArray<const char *, LAST> construct_names() {
    MyArray<const char *, LAST> r;
    r[FIRST] = "first";
    r[SECOND] = "second";
    return r;
}

static auto names = construct_names();

You may also want to read How to initialize private static members in C++? or similar, as for class initialization you need to do like, there will be some type repetition:

class MyClass {
public:
    static MyArray<const char *, LAST> names;
};

MyArray<const char *, LAST> MyClass::names = construct_names();
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
0

Yes you can do it in simple way using __attribute__((init_priority(101))) and __attribute__((constructor(102)))

#include <string>
#include <iostream>

using namespace std;

enum  MyEnum
{
   FIRST = 0,
   SECOND,
   LAST
};


class MyClass
{
public:
    static string names[LAST];
    
};

__attribute__((init_priority(101))) string MyClass::names[LAST];

__attribute__((constructor(102))) void foo()
{
    MyClass::names[FIRST] = "First";
    MyClass::names[SECOND] = "Second";
}


int main()
{
    MyClass m;
    for (int i = 0; i < LAST; i++) {
        cout << m.names[i] << "\n";
    }
}

Output:

First
Second

Explanation in simple:

Before even code loads, first it initialize string MyClass::names[LAST]; because we added __attribute__((init_priority(101))) then it calls foo() automatically, The function name can be any it does not matter, it can be init as well no need to be foo. The order of initialization is based on number 101 and 102. If we change the order then it wont work.

For more info refer: https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#index-init_005fpriority-variable-attribute

Declaimer: This initialization is not bound to the class, if you keep on adding like this for all the classes then you are in big trouble and you need to keep on maintain a list of orders. This inits are for the entire binary or library

Bhavith C
  • 72
  • 5