[ACCEPTED]-C++, can I statically initialize a std::map at compile time?-embedded

Accepted answer
Score: 38

It's not exactly static initialization, but 4 still, give it a try. If your compiler doesn't 3 support C++0x, I'd go for std::map's iteration constructor:

std::pair<int, std::string> map_data[] = {
    std::make_pair(1, "a"),
    std::make_pair(2, "b"),
    std::make_pair(3, "c")

std::map<int, std::string> my_map(map_data,
    map_data + sizeof map_data / sizeof map_data[0]);

This 2 is pretty readable, doesn't require any 1 extra libraries and should work in all compilers.

Score: 22

Not in C++98. C++11 supports this, so if 3 you enable C++11 flags and include what 2 g++ suggests, you can.

Edit: from gcc 5 C++11 1 is on by default

Score: 14

You can use Boost.Assign library:

#include <boost/assign.hpp>
#include <map>
int main()
   std::map<int, char> example = 
      boost::assign::map_list_of(1, 'a') (2, 'b') (3, 'c');

However, as Neil and 3 others pointed in the comments below, this 2 initialization occurs in runtime, similarly 1 to UncleBean's proposal.

Score: 14

With C++0x you might need to use braces 12 all the way (use the new-style syntax for 11 each pair as well):

std::map<int, char> example = { {1,'a'}, {2, 'b'}, {3, 'c'} };

Those brackets to construct 10 pairs are not meaningful. Alternatively 9 you can fully name out each pair or use 8 make_pair (as you'd do in C++98)

std::map<int, char> example = {
    std::make_pair(2, 'b'),
    std::make_pair(3, 'c')

As to creating 7 those instances at compile-time: no. STL 6 containers all encapsulate entirely runtime 5 memory management.

I suppose, you'd only 4 really have a compile-time map with libraries 3 like boost's metaprogramming (not 100% sure, if 2 it is entirely correct, and haven't studied 1 what it could be good for):

using namespace boost::mpl;
    pair<integral_c<int, 1>, integral_c<char, 'a'> >,
    pair<integral_c<int, 2>, integral_c<char, 'b'> >,
    pair<integral_c<int, 3>, integral_c<char, 'c'> >
> compile_time_map;
Score: 4

With pre-C++0x, the closest thing you can 16 get is by not using containers designed 15 for runtime usage (and limiting yourself to fundamental types and aggregates):

struct pair { int first; char second; };
pair arr[] = {{1,'a'}, {2,'b'}}; // assuming arr has static storage

This could then be accessed 14 using some kind of map view, or you could implement 13 a wrapper that allows for aggregate initialization 12 similar to what Boost.Array does.

Of course the question 11 is wether the benefits justify the time 10 put into implementing this.

If my reading 9 is correct here, C++0x initializer-lists 8 may give you static initialization of non-aggregates 7 like std::map and std::pair, but only if that doesn't change 6 semantics compared to dynamic initialization.
Thus, it seems to me you 5 can only get what you asked for if your 4 implementation can verify via static analysis 3 that the behaviour doesn't change if the 2 map is statically initialized, but no guarantees 1 that it happens.

Score: 1

There is a trick you can use, but only if 6 this data will not be used in any other 5 static constructor. First define a simple 4 class like this:

typedef void (*VoidFunc)();
class Initializer
    Initializer(const VoidFunc& pF)

Then, use it like this:

std::map<std::string, int> numbers;
void __initNumsFunc()
  numbers["one"] = 1;
  numbers["two"] = 2;
  numbers["three"] = 3;
Initializer __initNums(&__initNumsFunc);

Of 3 course this is a bit overkill so I would 2 recommend using it only if you really have 1 to.

Score: 1

There is no standard way to initialize std::map at 12 compile time. As others have mentioned, C++0x 11 will allow the compiler to optimize the 10 initialization to be static if possible, but 9 that will never be guaranteed.

Remember, though, that 8 the STL is just an interface spec. You can 7 create your own compliant containers and 6 give them static initialization capability.

Depending 5 on whether you plan on upgrading your compiler 4 and STL implementation (particularly on 3 an embedded platform), you might even just 2 dig into the implementation you're using, add 1 derived classes, and use those!

More Related questions