Home > Enterprise >  How to initialize a class variable using a for loop in C ?
How to initialize a class variable using a for loop in C ?

Time:01-06

My example class has a static array of characters, and I want to create a map from the characters to the indices. I need to initialize this static map in a for loop in my "example.cpp" file. However, C "expects a declaration". Is there any way of populating my map as a declaration? In general, is it possible to create a constructor for the static variables that handles all this initialization before the constructor for the class variables is called?

Here is my example class.

#include <map>
using namespace std;
class Example {
    static char chars[4];
    static map<char,int> char2idx;
};

char Example::chars[4] = {'a','b','c','d'};
for(int i=0; i<4;i  ) {
    Example::char2idx[Example::chars[i]] = i;
}

I am getting the following error when I try to compile.

clang   -std=c  11 -Wall -g -c -o example.o example.cpp
example.cpp:9:1: error: expected unqualified-id
for(int i=0; i<4;i  ) {
^
1 error generated.

CodePudding user response:

Quick fix: Make a helper function

#include <map>
using namespace std;
class Example {
    friend map<char,int> helper(); // so it can see the private members
    static char chars[4];
    static map<char,int> char2idx;
};

map<char,int> helper() // does the work, returns the map
{
    map<char,int> out;
//    for(int i=0; i<4;i  ) {  that four is ugly. What if chars changes in size?
    for(int i=0; i<std::size(Example::chars);i  ) { // if we didn't want i I'd use 
                                                    // a range-based for to make 
                                                    // life even simpler.  
        out[Example::chars[i]] = i;
    }
    return out; // return by value. copy elision is your friend!
}


char Example::chars[4] = {'a','b','c','d'};
map<char,int> Example::char2idx = helper(); 

CodePudding user response:

The ur-example in C is how std::cin, std::cout, etc are initialized. The core trick is to have a local static variable in the global namespace that calls the static constructor:

example.hpp

class Example
{
  static stuff here;
  static bool initialize();
};

static bool b_initialize_Example = Example::initialize();

example.cpp

bool Example::initialize()
{
  static bool is_initialized = false;
  if (!is_initialized)
  {
    // do your for loop here.
  }
  return is_initialized = true;
}

Anther way is to use a factory to generate instances of your class. The first time you generate an instance, initialize the static data.

// No example here. Google around factory methods.
// You’ll still need a static bool is_initialized somewhere.

Finally, you can just use a static initializer in your class’s constructor. This is similar to the first method:

class Example
{
  Example() { initialize(); ... }

  static void initialize()
  {
    static bool is_initialized = false;
    if (is_initialized) return;
    // initialize stuff here
    is_initialized = true;
  }
};

I’m sure there are other ways to go about this, but that’s what is on the top of my head.

EDIT: the example in the other answer is nice too!

  • Related