Initialization are perform line by line as @ecatmur wrote. So:
- std::map foo::sqlenumToInt = initEnumToInt();
- std::map foo::defaultIt = std::map::iterator();
To explain it i've write simple example:
// foo.h
#pragma once
#include <iostream>
struct bar
{
int value_;
bar(int value)
{
std::cout << "bar()\n";
set(value, true);
}
void set(int value, bool fromConstructor = false)
{
std::cout << ((fromConstructor) ? "Set from ctor" : "Set from non-ctor")
<< ", old value is: " << value_ << "\n";
value_ = value;
}
};
struct foo
{
static bar bar_;
static bool init()
{
std::cout << "init begin\n";
bar_.set(1);
std::cout << "init end\n";
return true;
}
};
// main.cpp
#include "foo.h"
bool b = foo::init();
bar foo::bar_ = bar(2);
int main()
{
std::cout << foo::bar_.value_ << "\n";
return 0;
}
And output is:
init begin
Set from non-ctor, old value is: 0
init end
bar()
Set from ctor, old value is: 1
2
So, memory for static variable are allocated but initialization are perform later, similar "placement new" mechanic. You can see in output that c'tor of bar are called after init, but old value is 1 (which will be set by init method) and overwrite to 2 due static initialization.
So, you can easy resolve that by changing order static initialization. But you have another problem described by @Kerrek SB:
(Moreover, even the iterator that you obtained in your function would
be meaningless, since it becomes invalid as soon as the local map
object is destroyed.)
One of variant to correct your case:
class foo
{
typedef std::map<std::string, int> Map;
static bool initEnumToInt();
static Map sqlenumToInt;
static Map::iterator defaultIt;
static bool inited;
};
foo::Map foo::sqlenumToInt;
foo::Map::iterator defaultIt = foo::Map::iterator();
bool foo::sqlenumToInt = initEnumToInt();
bool foo::initEnumToInt();
{
defaultIt = sqlenumToInt.insert(std::make_pair("a", 0)).first;
sqlenumToInt["b"] = 2;
sqlenumToInt["c"] = 3;
sqlenumToInt["d"] = 4;
return true;
}