Search code examples
c++initializationcurly-braces

How to initialize recurring `std::unordered_map` via curly braces


I need to initialize a type implementing tree-like structure.

Tree t1 = 1;
Tree t2 = {{"a",t1},{"b",{{"x",2},{"y",4}}},{"c",5}};

So i defined structure which inherits from std::unordered_map. I had to wrap recurring Tree in smart pointer.

//tree.h
    using std;
    struct Tree : unordered_map<string, unique_ptr<Tree>>{
        int simple;
    
        Tree() = default;
        Tree(unsigned s): simple{s}{};
        Tree(const initializer_list<pair<string, unique_ptr<Tree>>> & il): simple{s} {
            // does not compile, would not work anyway 'coz the pointer
        }
    };

I can't figure out how to specify the initializer list.

there is something that might help:

struct TreeV : vector<pair<string, TreeV>>{
...
TreeV(const vector<pair<string, TreeV>> & v) : vector<pair<string, TreeV>>(v){};
}
vector<pair<string, TreeV>> t3 = {{"a",t1},{"b",{{"x",2},{"y",4}}},{"c",5}};

How can I catch recurrent curly braces structure in the 'initializer_list'? or How can I initialize recurring pattern of std::unordered_map from curly braces structure?


Solution

  • Remove the reference from the initializer list. You cannot pass rvalues while using non const references. Also remove the simple{s} from the member initializer list if s isn't even defined anywhere.

    Tree(std::initializer_list<std::pair<std::string, std::unique_ptr<Tree>>> il) {};
    

    Then something like this would compile.

    Tree t = { 
      { "one", std::make_unique<Tree>() },
      { "two", std::unique_ptr<Tree>(new Tree({ // unique_ptr is used here because make_unique does not support initializer lists.
        {
          "three", std::make_unique<Tree>()
        }}))
      }
    };
    

    But I would question the use of unique_ptr altogether, is there a particular reason for using them here? I assume the memory would be managed by the unordered_map anyways? Here's how it would look without the use of unique_ptr:

    // This would allow to use syntax that resembles your goal
    Tree(std::initializer_list<std::pair<std::string, Tree>> il) {};
    ...
    Tree t = { 
      { "one", {} },
      { "two", {
          { "three", {} }
        }
      }
    };