In class static map initialization

Hi, I have a class containing a map member that I want to initialize at declaration time. I know I can do it in the cpp file but I'm having a problem with the order of initialization (static initialization order fiasco).

My questions are:

Is it possible that the scenario in which, the Test's constructor's implementation and the map initialization instruction are in the same cpp file and constructor is called when the map is not initialized yet, could happen?

Is it possible to initialize the map in class like I did?
I get these errors:
in-class initialization of static data member 'std::map<std::basic_string<char>, Test*> Test::a' of incomplete type
temporary of non-literal type 'std::map<std::basic_string<char>, Test*>' in a constant expression
If yes, does this initialization resolve the static initialization order fiasco?

1
2
3
4
5
6
7
8
9
10
11
12
class Test {
public:
	static std::map<std::string, Test*> a = {};//this is an error
	Test(std::string ID) {
		/* in my complete code  (where constructor
		 * implementation and map initialization
		 * are in a separate .cpp file), this fails, maybe
		 * because the map is not initialized at the time
 		 * the constructor is being called by a sub class of Test */
		a.insert({ID, this});
	}
};
Last edited on
Is it possible to initialize the map in class like I did?
Only static constants can be initialized that way.

Is it possible that the scenario in which, the Test's constructor's implementation and the map initialization instruction are in the same cpp file and constructor is called when the map is not initialized yet, could happen?
It requires in-depth Standard reading, but the only way when this scenario potentially could happen if you have global variable Test, which tries to access map in its constructor.
Is StaticPool<Binary>::pool[] elements considered a global variable of OperatorCore (named Test in the example above)?

This is the minimal code when the problem occur.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
//Binary.hpp
class Binary final : public OperatorCore, public StaticPool<Binary> {
public:
    Binary(int ID, std::string name)
        : OperatorCore(name), StaticPool<Binary>(ID) {
    }
    ~Binary() {}
};
//Binary.cpp
template<>
const Binary StaticPool<Binary>::pool[] = {
    /* this calls OperatorCore's constructor (named Test in the first post)
     * where is the insertion in the map instruction */
    Binary(0, "a string value")
};




//OperatorCore.hpp
class OperatorCore {
public:
    static std::map<std::string, OperatorCore*> symbolMap;
    const std::string name;
    OperatorCore (std::string name);
    virtual ~OperatorCore () {}
};
//OperatorCore.cpp
std::map<std::string, OperatorCore*> OperatorCore::symbolMap{};
OperatorCore::OperatorCore(std::string name) : name(name) {
    symbolMap.insert({name, this});//without this line of code, it prints works
}




//StaticPool
template<typename T, typename TKey = int>
class StaticPool {
public:
    const TKey ID;
    static const T pool[];
    StaticPool(TKey ID) : ID(ID) {}
    virtual ~StaticPool() {}
};


I can't imagine how it can execute the code of the constructor (of class OperatorCore) without having initialized the map if they are in the same translation unit.

Isn't the translateion unit sequential?
Last edited on
It is a little complex with templates, but even if everything is ordered, StaticPool<Binary>::pool[] is initialised before OperatorCore::symbolMap.

And in pool initialization Binary constructor is called, which calls OperatorCore constructor which tries to use uninitialized symbolMap
I will use the map as a static local variable of a function that returns it. Thank you!
Last edited on
Topic archived. No new replies allowed.