towi
towi

Reputation: 22267

C++0x: Overload Resolution

In the Standard-Text there is an example in 8.5.4 (3) List-initialization [dcl.init.list]

struct S {
    S(std::initializer_list<double>);  // #1
    S(const std::string&);             // #2
};
const S& r1 = { 1, 2, 3.0 };  // OK: invoke #1
const S& r2 { "Spinach" };    // OK: invoke #2 !!!

(the example is about the ref-to-temp, but I refer to the overload resolution here).

Whereas Scott Meyers in his talk/slides tells a different story:

std::initializer_list parameters are always preferred over other types:

class Widget {
public:
    Widget(double value, double uncertainty);           // #1
    Widget(std::initializer_list<std::string> values);  // #2
};
double d1, d2;
Widget w1 { d1, d2 }; // tries to call #2; fails because
                      // no double ⇒ string conversion

The examples are slightly different, but aren't those about the same thing? When and how overload resolution with initializer_list-constructors happens? Or is there a different issue here?

How is the overloading decided in both cases? If both are correct, what do I miss here?

Edit/Clarification upon Keric's Comment: My feeling ist, that the two examples contradict each other:

Of course, the Std is always right, but maybe I apply the example wrongly. The Std example has & in it, that I don't think are relevant for my question, but maybe I am wrong.

Scott's slides are quite recent, and I can not see that the relevant section(s) in the Std have changed to that respect (although, it's difficult to get everything into scope, because it's somewhat "widely spread" :-)

Edit-2: I got a mail from Scott himself that there was a late change in the Standard that had not been incorporated into the slides.

Upvotes: 3

Views: 233

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473222

Pursuant to N3291, the Working Draft from April 5, 2011, there has been a few changes to initializer lists, so Scott Meyer's slides may be from old data.

According to section 13.3.1.7 (so close to 1337):

  • Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument
  • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

So it does prefer initailizer lists. But if the initializer list doesn't match, then it will check the regular constructors to see if they match.

It goes on to say that if the initializer list is empty, then the default constructor is used.

Upvotes: 5

Related Questions