Mano Mini
Mano Mini

Reputation: 613

How to initialize unordered_map<string, unordered_set<string>> members using initializer list?

I have this class

class A {
    unordered_map<string, unordered_set<string>> n_;
  public:
    A(unordered_map<string, unordered_set<string>>& n) : n_{n} {}
};

And I want to be able to use the constructor with that syntax

int main() {
    A a{{"C", {"A", "B"}}};
    return 0;
}

But in the way it's written now, I'm getting error

error: no matching function for call to `‘A::A(<brace-enclosed initializer list>)’ A a{{"C", {"A", "B"}}};`

How can it be fixed?

Upvotes: 4

Views: 2539

Answers (4)

JeJo
JeJo

Reputation: 32852

I want to be able to use the constructor with that syntax

You can provide an std::initializer_list constructor to do the job

#include <initializer_list>

class A
{
    using MapType = std::unordered_map<std::string, std::unordered_set<std::string>>;
    MapType n_;
public:
    A(std::initializer_list<MapType::value_type> n) : n_{ n } {}
    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
};

which has the advantage that list initialization does not require an extra pair of {}. For example maps with two entries:

A a{
    {"C", {"A", "B"}},
    {"D", {"E", "F"}},
}; // do not require extra braces now!

(See Live)

Upvotes: 4

songyuanyao
songyuanyao

Reputation: 172924

You need to add one more {} for it. And note that temporary can't be bound to lvalue-reference to non-const. (They could be bound to lvalue-references to const or rvalue-references.) e.g.

class A {
    unordered_map<string, unordered_set<string>> n_;
  public:
    A(const unordered_map<string, unordered_set<string>>& n) : n_{n} {}
    //^^^^^
};

int main() {
    A a{{{"C", {"A", "B"}}}};
    //          ^^^  ^^^     elements of unordered_set
    //         ^^^^^^^^^^    for the unordered_set
    //   ^^^^^^^^^^^^^^^^^   elements (std::pair) of unordered_map (only one here)
    //  ^^^^^^^^^^^^^^^^^^^  for the unordered_map
    // ^^^^^^^^^^^^^^^^^^^^^ for A

    return 0;
}

I guess you might miss the {} for the elements (std::pair) of the unordered_map; in a similar fashion, if you want to make the unordered_map containing two elements, you can write it as

A b{{{"C", {"A", "B"}}, {"F", {"D", "E"}}}};

LIVE

Upvotes: 8

Yksisarvinen
Yksisarvinen

Reputation: 22219

On top of Jarod's (correct) answer, you are missing one set of curly braces:

int main() {
    A a{{{"C", {"A", "B"}}}};
    return 0;
}

From the innermost ones:

You need to initialize std::unordered_set:

{"A", "B"}

Use that set in instance of std::pair

{"C", {"A", "B"}}

Use that pair to initialize std::unordered_map:

{{"C", {"A", "B"}}}

Use that map to initialize an object of A:

A a{{{"C", {"A", "B"}}}};

Upvotes: 3

Jarod42
Jarod42

Reputation: 217293

Temporary cannot bind to non-const (lvalue) reference.

You might change constructor to

A(const unordered_map<string, unordered_set<string>>& n) : n_{n} {}

or

A(unordered_map<string, unordered_set<string>>&& n) : n_{std::move(n)} {}

or

A(unordered_map<string, unordered_set<string>> n) : n_{std::move(n)} {}

Upvotes: 2

Related Questions