9

Overload resolution favours to consider {} as being of some fundamental type as opposed to some container.

For example:

#include <iostream>
#include <string>

void foo(const std::string&) {std::cout << "string\n";}
void foo(int) {std::cout << "int\n";}

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

That compiles without any diagnostics and outputs:

int

https://godbolt.org/z/zETfrs5as

If to comment out the int overload then it works fine with string.

The question is why? For programmer's standpoint it can be confusing illusion.

Marek R
  • 32,568
  • 6
  • 55
  • 140
Öö Tiib
  • 10,809
  • 25
  • 44

1 Answers1

9

From over.ics.list#9.2:

if the initializer list has no elements, the implicit conversion sequence is the identity conversion. [ Example:

 void f(int);

 f( { } );               // OK: identity conversion

 — end example ]

Thus, the conversion from {} to int is an identity conversion, while {} to const std::string& is a user-defined conversion. And since the identity conversion is a better match, the overload corresponding to int will be chosen.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Jason
  • 36,170
  • 5
  • 26
  • 60