0

When I construct an unordered_set using an initialize list of three or more items, my compiler (Solstudio 12.4) compiles without complaint:

unordered_set<string> sam({"a", "b", "c"});

However, if I reduce the number of items in the initializer list to exactly 2, the compiler complains

unordered_set<string> bob({"a", "b"});

Error: Overloading ambiguity between

"std::unordered_set, std::equal_to, std::allocator>::unordered_set( std::initializer_list, unsigned long, const std::hash&, const std::equal_to&, const std::allocator&)" and

"std::unordered_set, std::equal_to, std::allocator>::unordered_set( std::unordered_set, std::equal_to, std::allocator>&&)". 1 Error(s) detected.

I'm pretty sure I can cast this error away but I'm curious about why the compiler chokes for this case. Any ideas?

Mustafa Ozturk
  • 812
  • 4
  • 19

1 Answers1

1

Looks like your compiler has bug, since when you construct from initializer_list constructor, that receives initializer_list should be preffered.

In your case second constructor is copy constructor, so, looks like compiler have two variants:

unordered_set<string> bob(unordered_set<string>{"a", "b"})

and

unordered_set<string> bob({"a", "b"});

Thanks to 0x499602D2, for explanation, actually unordered_set has constructor, that takes two iterators and in your case compiler takes it, that is incorrect, since initializer_list constructor should be preffered. You can try to use following:

unordered_set<string> bob{"a", "b"};
ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • Seems that way. Very bizarre though, why would a init list of one item work and N items work, but not two? – Mustafa Ozturk Mar 20 '15 at 13:59
  • @MustafaOzturk have no idea, but you can just look at unordered_set header and looks at constructors of unordered_set. – ForEveR Mar 20 '15 at 14:06
  • 2
    @MustafaOzturk `std::unordered_set` has a constructor that takes iterators (two arguments deduced by templates). Your strings can act as iterators as they can be converted to pointers. Your compiler is incorrectly choosing that overload. – David G Mar 20 '15 at 14:10
  • @0x499602D2 I'm not providing it two arguments though, I'm providing the constructor one argument (the initializer list) which in turn has two elements. Logged a question to oracle. – Mustafa Ozturk Mar 20 '15 at 14:12
  • @MustafaOzturk The braces can construct a temporary `unordered_set` and then the initializer clauses `"a"` and `"b"` are the arguments to its constructor. That's why you have an ambiguity between the copy-constructor and the one taking an initializer list. – David G Mar 20 '15 at 14:17
  • Thanks to both of you. That explains it. – Mustafa Ozturk Mar 20 '15 at 14:25
  • @0x499602D2 Am I misunderstanding the link from @NathanOliver? It seems to be explaining that it's not a compiler bug: http://stackoverflow.com/a/24112395/4342498 – PeterSW Mar 20 '15 at 16:07
  • @PeterSW I'm not sure if it's a bug either, but it's not unsurprising behavior to me. – David G Mar 20 '15 at 16:17