From -2794511676994472821
X-Google-Thread: 7894ca11fe,bda36747929f8c7f
X-Google-Attributes: gid7894ca11fe,public,usenet
X-Google-NewGroupId: yes
X-Google-Language: ENGLISH,ASCII-7-bit
Path: g2news2.google.com!news1.google.com!Xl.tags.giganews.com!border1.nntp.dca.giganews.com!nntp.giganews.com!local2.nntp.dca.giganews.com!news.giganews.com.POSTED!not-for-mail
NNTP-Posting-Date: Sat, 31 Oct 2009 22:10:15 -0500
Return-Path: <cppmods@ruralroute.cs.rpi.edu>
To: (Usenet)
From: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Newsgroups: comp.std.c++
Subject: Re: How many parameters in T({x, y, z}) ?
Followup-To: comp.std.c++
Organization: T-Online
Sender: cppmods@cs.rpi.edu
Approved: stephen.clamage@sun.com
Message-ID: <hchqf3$95s$00$1@news.t-online.com>
References: <hcghm3$ifu$1@news.albasani.net>
Content-Type: text/plain; charset="ISO-8859-1"
X-Original-Date: Sat, 31 Oct 2009 17:58:35 +0100
X-Submission-Address: std-c++@netlab.cs.rpi.edu
Date: Sat, 31 Oct 2009 22:06:31 CST
Lines: 90
X-Usenet-Provider: http://www.giganews.com
X-Trace: sv3-SxbfPwXX9LEJ0e1HwGQVlzk6G0GiRjPcS/aD50xMleSGt1P055cRDguiHtCrN9wQ6DpKb6XcrsoBRXk!YLjtbfBKePO90PDOSgRrWZmCHuFPUtI8d65JXrU1vAt+5rn+n4aJuz3TrMBu
X-Complaints-To: abuse@giganews.com
X-DMCA-Notifications: http://www.giganews.com/info/dmca.html
X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers
X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly
X-Postfilter: 1.3.40
Xref: g2news2.google.com comp.std.c++:1624

Scott Meyers wrote:

> Consider the following attempt to construct a Widget object:
> 
>    Widget w( {5, 10, 15} );
> 
> How many arguments are being passed to the constructor?  I say one, and
> gcc 4.4 seems to agree with me:
> 
> #include <iostream>
> #include <initializer_list>
> 
> class Widget {
> public:
>    Widget(int, int, int) { std::cout << "3 ints\n"; }
> private:
>    Widget(const Widget&) { std::cout << "copy\n"; }
> };
> 
> int main()
> {
>    Widget w ({ 10, 20, 30 });   // error! copy ctor is private
> }
> 
> Presumably the compiler is trying to create a temporary from the 3-int
> constructor to pass to the copy constructor, which it thinks I'm trying to
> call by passing only one constructor argument.
> 
> If this is the case, adding a constructor taking an initializer_list
> should make
> no difference:  I'd still be calling a constructor with a single argument.
>  The initializer_list constructor would be called to create the temporary,
> but I'd
> still have to have access to the copy constructor.  But that's not what
> gcc does:
> 
> #include <iostream>
> #include <initializer_list>
> 
> class Widget {
> public:
>    Widget(int, int, int) { std::cout << "3 ints\n"; }
>    Widget(std::initializer_list<int>) { std::cout << "init list\n"; }
> private:
>    Widget(const Widget&) { std::cout << "copy\n"; }
> };
> 
> int main()
> {
>    Widget w ({ 10, 20, 30 });   // compiles, runs, prints "init list"
> }
> 
> Is this a bug in my understanding or a bug in gcc's implementation?
> 
There is a subtle difference that i think is worth noting so it's clear:

Widget w{10, 20, 30};

Is different from the following

Widget w({10, 20, 30});

The first is list-initialization, and will end up in 13.3.1.7 for finding
candidates, and the second is direct initialization (because the initializer
is a braced expression list), and ends up at 13.3.1.3. So in fact the
argument in your case consists of 1 instead of 3 arguments - so only the
copy constructor is viable. For this, 13.3.3.1.5 does the mapping to the
three forms of implicit conversion sequences, and selects 13.3.3.1.5/5, and
the reference binding will make the conversion sequence a user defined
conversion sequence by going back to 13.3.3.1.5/3.

Now, if you add the initializer list, there are two viable candidate
functions, instead of only one: The initializer list constructor, and the
copy constructor. 13.3.3.1.5 maps the conversion sequence for the
initializer list constructor to an identity conversion by 13.3.3.1.5/2. In
this case, the copy constructor is still viable, but reference binding is
going back to 13.3.3.1.5/3 again (because it converts the initializer list
to "Widget" - *not* to initializer_list<int> which is merely a parameter of
the constructor used in the user defind conversion sequence.

Since using the initializer list ctor results in a better conversion
sequence, it's used over the copy constructor by GCC. I think GCC does it
all right here.

-- 
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]



