C++ Initialize unordered_map by method called by Constructor initializer list throws exception

97 views Asked by At

I'm trying to populate an unordered_map [class member] in a method called in the Constructor initializer list. I get a runtime exception at map[0] = 1 which seems to be due to the member not being constructed prior to the method being called. (I put a breakpoint on the unordered_map constructor and it was not hit). Is there a way to force the construction of the unordered_map member prior to the method being called?

#include <iostream>
#include <unordered_map>

class Base
{
public:
   Base(int chan) { }
};
class Foo : public Base
{
   std::unordered_map<int, int> map;
   int Init(int chan)
   {
      // fill map
      map[0] = 1;
      map[1] = 3;
      return map[chan];
   }
public:
   Foo(int chan) : Base(Init(chan)) { }
};

int main()
{
   Foo foo(0);
}

Using Visual Studio 2019.

1

There are 1 answers

3
Igor Tandetnik On BEST ANSWER

Off the top, here are two ideas I have. First:

struct MapWrapper {
  std::unordered_map<int, int> map;
};

class Foo : private MapWrapper, public Base {
  /* The rest of the class can remain unchanged, except that
     there's no `map` member; it's inherited from MapWrapper */
};

This forces map to be constructed before Base.


Second:

class Foo : public Base
{
   std::unordered_map<int, int> map;

   static std::unordered_map<int, int> MakeMap() {
     std::unordered_map<int, int> map;
     map[0] = 1;
     map[1] = 3;
     return map;
   }
   Foo(int chan, std::unordered_map<int, int>&& temp_map)
     : Base(temp_map[chan]), map(std::move(temp_map)) {}
public:
   Foo(int chan) : Foo(chan, MakeMap()) {}
};

This uses delegating constructor trick to essentially simulate a local variable in the constructor initializer list.