Topic: N2215: Size 0 initializer lists


Author: jgottman@carolina.rr.com (Joe Gottman)
Date: Tue, 27 Mar 2007 23:50:49 GMT
Raw View
Steve Ward wrote:
> On Mar 27, 1:09 am, Joe Gottman <jgott...@carolina.rr.com> wrote:
>> What is the deduced type of a size 0 initializer list, such as in the
>> following statement?
>>     vector<int> foo =3D {};
>>
>> Obviously there is no type associated with {}.  Does this mean that if=
 a
>>   class can be initialized from two different types of initializer lis=
ts
>> it cannot be initialized from an empty one?
>>

>=20
>=20
> Perhaps this section in the paper has the answer:
>=20
> "
> 4.7.1 Aggregate initialization
>=20
> In line with our ideal of allowing initializer lists just about
> everywhere - and following existing rules - we can initialize a non-
> aggregate with an initializer list with 0 or 1 element. The empty
> initializer list gives value initialization. The reason to extend the
> use of initializer lists in this direction is to get a uniform
> mechanism for initialization. In particular, we don't have to worry
> about whether a type is implemented as a built-in or a user-defined
> type and we don't have to depart from the direct initialization to
> avoid the unfortunate syntax clash between () initialization and
> function declaration. For example:
> X a =3D { v };
> X b =3D { };

    That's a design goal.  I'm not convinced that the initializer_list=20
proposal, as currently written, achieves that goal.  Consider the=20
following passage from section 4.1:

The general rule of the use of initializer lists is:
     1. If a constructor is declared
         1. If there is a sequence constructor that can be called for=20
the initializer list
             1. If there is a unique best sequence constructor, use it
             2. Otherwise, it=92s an error


Now apply these rules to the following code:

     struct Foo {
         Foo(initalizer_list<int>);
         Foo(initializer_list<string>); // Two sequence constructors
     };

      Foo foo =3D {}; // Empty initializer_list, no best match.

The initializer_list {} can be passed to either sequence constructor,=20
and there's no way for the coder to specify that one should be preferred=20
over the other.  Nor is there a way for the coder to create a new=20
constructor that would be preferred over the two existing sequence=20
constructors in the case of an empty initializer_list.  Thus, if a class=20
possesses two sequence constructors it cannot be initialized using an=20
empty initializer_list.

Joe Gottman

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





Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Wed, 28 Mar 2007 18:22:59 GMT
Raw View
In article <4609aba6$0$28133$4c368faf@roadrunner.com>, Joe Gottman
<jgottman@carolina.rr.com> writes
>The initializer_list {} can be passed to either sequence constructor,
>and there's no way for the coder to specify that one should be
>preferred over the other.  Nor is there a way for the coder to create a
>new constructor that would be preferred over the two existing sequence
>constructors in the case of an empty initializer_list.  Thus, if a
>class possesses two sequence constructors it cannot be initialized
>using an empty initializer_list.

Well that looks very reasonable to me. And, of course, you can actually
initialise it by having a normal ctor and calling it with a different
initialisation syntax.


--
Francis Glassborow      ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

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





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Wed, 28 Mar 2007 18:42:00 GMT
Raw View
Joe Gottman ha scritto:
> Steve Ward wrote:
>>
>> Perhaps this section in the paper has the answer:
>>
>> "
>> 4.7.1 Aggregate initialization
>>
>> In line with our ideal of allowing initializer lists just about
>> everywhere - and following existing rules - we can initialize a non-
>> aggregate with an initializer list with 0 or 1 element. The empty
>> initializer list gives value initialization. The reason to extend the
>> use of initializer lists in this direction is to get a uniform
>> mechanism for initialization. In particular, we don't have to worry
>> about whether a type is implemented as a built-in or a user-defined
>> type and we don't have to depart from the direct initialization to
>> avoid the unfortunate syntax clash between () initialization and
>> function declaration. For example:
>> X a = { v };
>> X b = { };
>
>  <snip>
>
>     struct Foo {
>         Foo(initalizer_list<int>);
>         Foo(initializer_list<string>); // Two sequence constructors
>     };
>
>      Foo foo = {}; // Empty initializer_list, no best match.
>
> The initializer_list {} can be passed to either sequence constructor,
> and there's no way for the coder to specify that one should be preferred
> over the other.  Nor is there a way for the coder to create a new
> constructor that would be preferred over the two existing sequence
> constructors in the case of an empty initializer_list.  Thus, if a class
> possesses two sequence constructors it cannot be initialized using an
> empty initializer_list.

According to the quoted text, an empty initializer list shall be
equivalent to value-initialization. In the specific case, this means
(8.5/5):

"if T is a class type (clause 9) with a user-declared constructor
(12.1), then the default constructor for T is called (and the
initialization is ill-formed if T has no accessible default constructor);"

That said, a class with two sequence constructors *can* be initialized
using an empty initializer_list, provided it has a user-declared default
constructor also.

Regarding my puzzlement of my previous post, I came to the conclusion
that the example at the bottom of page 18:

  struct SS {
    SS() { }
    string a, b;
  };
  SS ss0 = { }; // error:

probably does not reflect what was meant to say. It should read instead:

  struct SS {
    SS() { }
    string a, b;
  };
  SS ss0 = {}; // ok: value-initialize through SS()
  SS ss1 = { "one", "two" }; // error

If I'm wrong and the example is indeed correct, I would like to know
what would be the rationale for rejecting my revised example, which
would (at last!) provide an explicit syntax for value-initialization
that can be very useful, IMHO.

Just my 2 eurocent,

Ganesh

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





Author: "=?iso-8859-1?q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Thu, 29 Mar 2007 14:07:22 CST
Raw View
[Note: This is a reposting of an answer some days ago, I hope
it's not too outdated now]

Alberto Ganesh Barbati schrieb:

> Cool, so we finally have an explicit syntax for value-initialization?
> But... wait... just a few paragraph below, in the same section it is said:
>
> "A class with a generated default constructor can co-exist with
> initializer list initialization. However, this would be an error:
>
>   struct SS {
>     SS() { }
>     string a, b;
>   };
>   SS ss0 = { }; // error:"
>
> so it seems to me that the intent of the last statement of the previous
> paragraph " we don't have to worry about whether a type is implemented
> as a built-in or a user-defined type" is, at least in part, defeated.
> What am I missing?

I have the same problem. And regrettably this limitation invalidates
some of the paper's own promises, e.g. on page 22 we have:

"A more interesting example might be

Map<string,int> m = { {"ardwark",91}, {"bison", 43} };

Assuming that map has a sequence constructor for from a
pair<string,int>, this will work, correctly converting the literal
strings to strings."

According to the specs of std::pair, the default constructor
is *not* the generated one, so consequently this should not
work.
One the other side, it also seems not reasonable to add
the constructor

template <class T1, class T2>
struct pair {
 ..
 template <typename U>
 pair(std::initializer_list<U>);
};

not only, because this would only support homogenous
pairs, but additionally we have to handle list sizes > 2.
(OK, provided that the size() member function *is* a
constexpr, we can do this:

 template <typename U>
 pair<T1, T2>::pair(std::initializer_list<U> src)
   first((static_assert(src.size() == 2, "Invalid initializer"),
src[0])),
   second(src[2])
 {
 }

but that seems somewhat horrible). To be fair, we must
recognize that Beman Dawes stumbled across similar
restrictions in his POD-extension proposal,

http://www2.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2172.html

IMO at least in case of the N2215 paper, I strongly propose,
that the empty initializer list is *always* valid and would simply
invoke the default c'tor (whether generated or not) or empty
sequence c'tor. Since the notion is new and explicit, I see no
reasons for possible unwanted performance killers, because the
old style is also valid and can be used, if really wanted.

This extension would also solve a problem in explicit specializations
of static data members, which I came aware by reading
"C++ Templates" (1st ed, p. 198). Consider:

class DefaultInitOnly {
public:
 DefaultInitOnly(){}
private:
 DefaultInitOnly(const DefaultInitOnly&);
};

template<typename T>
class Statics {
 static T sm;
};

template<>
DefaultInitOnly Statics<DefaultInitOnly>::sm; // Declaration, *no*
 // definition!

template<>
DefaultInitOnly Statics<DefaultInitOnly>::sm =
 DefaultInitOnly(); // Copy c'tor not available!

That is, in current C++ we have no valid syntax for
such a static data member definition. The following
would solve this problem:

template<>
DefaultInitOnly Statics<DefaultInitOnly>::sm = {}; // (a) Should work?
(not yet)

template<>
DefaultInitOnly Statics<DefaultInitOnly>::sm{}; // (b) Should work?
(not yet)

And yes, I'm aware of the ambiguity problem between
default c'tor and empty sequence c'tor invokation (discussed
and resolved in the paper). According to my interpretation, the
rules explained in section 4.1 of N2215 would simply result into
the case 1.2.1 of the case flow chart.

Greetings from Bremen,

Daniel Kr   gler


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





Author: Alberto Ganesh Barbati <AlbertoBarbati@libero.it>
Date: Thu, 29 Mar 2007 18:05:43 CST
Raw View
Daniel Kr   gler ha scritto:
>
> IMO at least in case of the N2215 paper, I strongly propose,
> that the empty initializer list is *always* valid and would simply
> invoke the default c'tor (whether generated or not) or empty
> sequence c'tor. Since the notion is new and explicit, I see no
> reasons for possible unwanted performance killers, because the
> old style is also valid and can be used, if really wanted.

Agreed, but see below...

> This extension would also solve a problem in explicit specializations
> of static data members, which I came aware by reading
> "C++ Templates" (1st ed, p. 198). Consider:
>
> class DefaultInitOnly {
> public:
>  DefaultInitOnly(){}
> private:
>  DefaultInitOnly(const DefaultInitOnly&);
> };
>
> template<typename T>
> class Statics {
>  static T sm;
> };
>
> template<>
> DefaultInitOnly Statics<DefaultInitOnly>::sm; // Declaration, *no*
>  // definition!
>
> template<>
> DefaultInitOnly Statics<DefaultInitOnly>::sm =
>  DefaultInitOnly(); // Copy c'tor not available!
>
> That is, in current C++ we have no valid syntax for
> such a static data member definition. The following
> would solve this problem:
>
> template<>
> DefaultInitOnly Statics<DefaultInitOnly>::sm = {}; // (a) Should work?
> (not yet)
>
> template<>
> DefaultInitOnly Statics<DefaultInitOnly>::sm{}; // (b) Should work?
> (not yet)

Yup! That's precisely the issue I had in mind.

> And yes, I'm aware of the ambiguity problem between
> default c'tor and empty sequence c'tor invokation (discussed
> and resolved in the paper). According to my interpretation, the
> rules explained in section 4.1 of N2215 would simply result into
> the case 1.2.1 of the case flow chart.

I would rather not fit the empty initializer list case in the general
rule described in 4.1. I believe that the simply stating "an empty
initializer list always means value-initialization" is easier to
understand and explain.

In order to make this principle work, I came to conclusion that the root
point here is in the definition of default constructor, which predates
the idea of initializer lists. The definition currently is (12.1/5): "A
default constructor for a class X is a constructor of class X that can
be called without an argument." [Note - I believe this definition is not
as good as it can be, because more than one constructor might satisfy
the condition at the same time. However, in such case none of them could
be used as THE default constructor, because it would be ambiguous. What
is the point in putting the "default constructor" label to something
that can't be used as such? - End note]

Back to the point, does an initializer-list-constructor satisfy the
requirement? What do we want it to be? There are pros and cons.

I see two options. The first one is that ctor taking an initializer list
cannot be called without arguments, so they can never be default
constructors. This has the advantage that I can make a
non-default-constructible class with an initializer-list-ctor (whether
this is reasonable/useful I don't know). The disadvantage is that if
have the "an empty initializer list always means value-initialization"
rule, then the programmer must write a default constructor explicitly.

The second option is to amend the definition of default constructor this
way:

1) A class type with user defined constructors has either one or no
default constructor. If it exists, the default constructor shall be
unambiguously selected in all contexts where an object is constructed
with no arguments or in presence of an empty initializer list.

2) In order to determine the default constructor, all constructors that
don't take initializer lists are considered:

  1) if there is exactly one constructor that can be called with no
arguments, it's the default constructor

  2) otherwise, if there are more than one constructors that can be
called with no arguments, there is no default constructor

3) otherwise, if there is exactly one constructor that take initializer
list, it is the default constructor

4) otherwise, there is no default constructor.

This definition, together with the "an empty initializer list always
means value-initialization" rule, has the following advantages:

a) a class that can has exactly one constructor taking an initializer
list does not need to define another constructor to be
default-constructible.

b) removes the "I have two default constructors therefore none of them"
embarrassment.

Any thoughts?

Ganesh

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





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: Fri, 30 Mar 2007 10:46:37 CST
Raw View
In article <XTWOh.41909$zG1.428079@twister2.libero.it>, Alberto Ganesh
Barbati <AlbertoBarbati@libero.it> writes
>I see two options. The first one is that ctor taking an initializer list
>cannot be called without arguments, so they can never be default
>constructors. This has the advantage that I can make a
>non-default-constructible class with an initializer-list-ctor (whether
>this is reasonable/useful I don't know). The disadvantage is that if
>have the "an empty initializer list always means value-initialization"
>rule, then the programmer must write a default constructor explicitly.

And how is that a problem? Sorry I really do not see what you are on
about. If I try to initialise and object (or sequence of objects) with
an empty initialiser list what do you think should happen if there is no
default ctor?

>
>The second option is to amend the definition of default constructor this
>way:
>
>1) A class type with user defined constructors has either one or no
>default constructor. If it exists, the default constructor shall be
>unambiguously selected in all contexts where an object is constructed
>with no arguments or in presence of an empty initializer list.

Not necessary we just specify that the list ctor forwards to the
appropriate ctor for each case and in the empty list case that is the
default ctor.

>
>2) In order to determine the default constructor, all constructors that
>don't take initializer lists are considered:
>
>  1) if there is exactly one constructor that can be called with no
>arguments, it's the default constructor
>
>  2) otherwise, if there are more than one constructors that can be
>called with no arguments, there is no default constructor
No, the program is ill-formed (as it is today) by virtue of ambiguity,
if and only if overload resolution results in more than one being
chosen.


>
>3) otherwise, if there is exactly one constructor that take initializer
>list, it is the default constructor

No because that would mean:

mytype mt();

would result in calling a list ctor if there was one.
What I would wish to see is:

mytype mt();

calls the default ctor if there is one else issues a diagnostic.

mytype mt = {};

calls the default ctor if there is one either indirectly through a list
ctor (and if there is more than one, still not ambiguous) or directly if
there is no list ctor.

>
>4) otherwise, there is no default constructor.
>
>This definition, together with the "an empty initializer list always
>means value-initialization" rule, has the following advantages:
>
>a) a class that can has exactly one constructor taking an initializer
>list does not need to define another constructor to be
>default-constructible.

And I strongly object to that as you wrote it. A class with an
initialiser list ctor and no default ctor cannot be initialised with an
empty list. And in accord with another proposal on the table at the
moment providing a default ctor in the presence of other ctors can be as
simple as writing:

   mytype() = default;

>
>b) removes the "I have two default constructors therefore none of them"
>embarrassment.

But IMHO, in the wrong way.

>
>Any thoughts?

--
Francis Glassborow      ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

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





Author: greghe@pacbell.net (Greg Herlihy)
Date: Fri, 30 Mar 2007 16:13:15 GMT
Raw View


On 3/29/07 5:05 PM, in article XTWOh.41909$zG1.428079@twister2.libero.it,
"Alberto Ganesh Barbati" <AlbertoBarbati@libero.it> wrote:

> Daniel Kr=FCgler ha scritto:

>> And yes, I'm aware of the ambiguity problem between
>> default c'tor and empty sequence c'tor invokation (discussed
>> and resolved in the paper). According to my interpretation, the
>> rules explained in section 4.1 of N2215 would simply result into
>> the case 1.2.1 of the case flow chart.
>=20
> I would rather not fit the empty initializer list case in the general
> rule described in 4.1. I believe that the simply stating "an empty
> initializer list always means value-initialization" is easier to
> understand and explain.
>=20
> In order to make this principle work, I came to conclusion that the roo=
t
> point here is in the definition of default constructor, which predates
> the idea of initializer lists. The definition currently is (12.1/5): "A
> default constructor for a class X is a constructor of class X that can
> be called without an argument." [Note - I believe this definition is no=
t
> as good as it can be, because more than one constructor might satisfy
> the condition at the same time. However, in such case none of them coul=
d
> be used as THE default constructor, because it would be ambiguous. What
> is the point in putting the "default constructor" label to something
> that can't be used as such? - End note]

No, there may be (at most) only one default constructor for a class. Note
the precise wording in the definition of a default constructor: a default
constructor "can" be called (not "may" be called) without any arguments. =
In
other words, a constructor that is simply allowed (under the rules of C++=
)
to be invoked without any arguments does not meet the definition of a
default constructor - to meet the definition, the constructor must actual=
ly
be called when no arguments are specified for an object's construction. F=
or
example:

    struct A
    {
         A( int i =3D 0) {}
         A( char *p =3D NULL) {}

    };

In this example, although both of A's constructors "may" be invoked witho=
ut
any explicit arguments, it is also true that neither of A's constructors
"can" be invoked without any arguments - because such a call is ambiguous
and invokes neither constructor. Therefore, class A has no default
constructor because it is not possible to call any of A's constructors
without providing at least one argument.
=20
> Back to the point, does an initializer-list-constructor satisfy the
> requirement? What do we want it to be? There are pros and cons.
>=20
> I see two options. The first one is that ctor taking an initializer lis=
t
> cannot be called without arguments, so they can never be default
> constructors. This has the advantage that I can make a
> non-default-constructible class with an initializer-list-ctor (whether
> this is reasonable/useful I don't know). The disadvantage is that if
> have the "an empty initializer list always means value-initialization"
> rule, then the programmer must write a default constructor explicitly.
>=20
> The second option is to amend the definition of default constructor thi=
s
> way:
>=20
> 1) A class type with user defined constructors has either one or no
> default constructor. If it exists, the default constructor shall be
> unambiguously selected in all contexts where an object is constructed
> with no arguments or in presence of an empty initializer list.

So why bother with the empty initializer list?

> 2) In order to determine the default constructor, all constructors that
> don't take initializer lists are considered:
>=20
>   1) if there is exactly one constructor that can be called with no
> arguments, it's the default constructor

This definition of a default constructor is the same as the current one.

>   2) otherwise, if there are more than one constructors that can be
> called with no arguments, there is no default constructor

Again, no change from the current definition.
=20
> 3) otherwise, if there is exactly one constructor that take initializer
> list, it is the default constructor
>=20
> 4) otherwise, there is no default constructor.
>=20
> This definition, together with the "an empty initializer list always
> means value-initialization" rule, has the following advantages:
>=20
> a) a class that can has exactly one constructor taking an initializer
> list does not need to define another constructor to be
> default-constructible.

Why not simply rely on a default argument for the initializer list to
provide default-construction? Doing so would preserve more flexibility in
deciding the class's design.

> b) removes the "I have two default constructors therefore none of them"
> embarrassment.

There is no such embarrassment in the current Standard. Instead, the
proposed text turns a one-sentence definition of a default constructor in=
to
a multi-paragraph "process" but that otherwise does not really change
anything.

Greg


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





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Sat, 31 Mar 2007 17:20:19 GMT
Raw View
Greg Herlihy ha scritto:
>>
>> In order to make this principle work, I came to conclusion that the root
>> point here is in the definition of default constructor, which predates
>> the idea of initializer lists. The definition currently is (12.1/5): "A
>> default constructor for a class X is a constructor of class X that can
>> be called without an argument." [Note - I believe this definition is not
>> as good as it can be, because more than one constructor might satisfy
>> the condition at the same time. However, in such case none of them could
>> be used as THE default constructor, because it would be ambiguous. What
>> is the point in putting the "default constructor" label to something
>> that can't be used as such? - End note]
>
> No, there may be (at most) only one default constructor for a class. Note
> the precise wording in the definition of a default constructor: a default
> constructor "can" be called (not "may" be called) without any arguments. In
> other words, a constructor that is simply allowed (under the rules of C++)
> to be invoked without any arguments does not meet the definition of a
> default constructor - to meet the definition, the constructor must actually
> be called when no arguments are specified for an object's construction.

Good point, I never read it that way. Now I see it. Thanks for the
clarification.

>
>> Back to the point, does an initializer-list-constructor satisfy the
>> requirement? What do we want it to be? There are pros and cons.
>>
>> I see two options. The first one is that ctor taking an initializer list
>> cannot be called without arguments, so they can never be default
>> constructors. This has the advantage that I can make a
>> non-default-constructible class with an initializer-list-ctor (whether
>> this is reasonable/useful I don't know). The disadvantage is that if
>> have the "an empty initializer list always means value-initialization"
>> rule, then the programmer must write a default constructor explicitly.
>>
>> The second option is to amend the definition of default constructor this
>> way:
>>
>> 1) A class type with user defined constructors has either one or no
>> default constructor. If it exists, the default constructor shall be
>> unambiguously selected in all contexts where an object is constructed
>> with no arguments or in presence of an empty initializer list.
>
> So why bother with the empty initializer list?

Why? Well, that's precisely the point! Because I would like

  T t = {};

to possibly invoke the default constructor.

>
>> 2) In order to determine the default constructor, all constructors that
>> don't take initializer lists are considered:
>>
>>   1) if there is exactly one constructor that can be called with no
>> arguments, it's the default constructor
>
> This definition of a default constructor is the same as the current one.

As I also answered to Francis Glassborow, this was meant to be algorithm
in multiple steps, which shall be read as a whole, not a list of options
to be discussed independently.

>>   2) otherwise, if there are more than one constructors that can be
>> called with no arguments, there is no default constructor
>
> Again, no change from the current definition.
>
>> 3) otherwise, if there is exactly one constructor that take initializer
>> list, it is the default constructor
>>
>> 4) otherwise, there is no default constructor.
>>
>> This definition, together with the "an empty initializer list always
>> means value-initialization" rule, has the following advantages:
>>
>> a) a class that can has exactly one constructor taking an initializer
>> list does not need to define another constructor to be
>> default-constructible.
>
> Why not simply rely on a default argument for the initializer list to
> provide default-construction? Doing so would preserve more flexibility in
> deciding the class's design.

That's an interesting point. I didn't realize that constructors taking
initializer lists might have default arguments. Default arguments don't
coexists well with my proposed equivalence of T t = {}; with value
initialization. Consider this case:

  struct T
  {
    T(initializer_list<int> l = { 1 });
  };

  T t = {};

is T::T() called with {} or with { 1 } ?

It seems that I found myself the perfect example of a fault in my
proposal...

Ganesh

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





Author: Joe Gottman <jgottman@carolina.rr.com>
Date: Mon, 26 Mar 2007 23:09:50 CST
Raw View
What is the deduced type of a size 0 initializer list, such as in the
following statement?
    vector<int> foo = {};

Obviously there is no type associated with {}.  Does this mean that if a
  class can be initialized from two different types of initializer lists
it cannot be initialized from an empty one?

Joe Gottman

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





Author: "Steve Ward" <planet36@gmail.com>
Date: Tue, 27 Mar 2007 00:41:15 CST
Raw View
On Mar 27, 1:09 am, Joe Gottman <jgott...@carolina.rr.com> wrote:
> What is the deduced type of a size 0 initializer list, such as in the
> following statement?
>     vector<int> foo = {};
>
> Obviously there is no type associated with {}.  Does this mean that if a
>   class can be initialized from two different types of initializer lists
> it cannot be initialized from an empty one?
>
> Joe Gottman
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-...@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html                     ]



Perhaps this section in the paper has the answer:

"
4.7.1 Aggregate initialization

In line with our ideal of allowing initializer lists just about
everywhere - and following existing rules - we can initialize a non-
aggregate with an initializer list with 0 or 1 element. The empty
initializer list gives value initialization. The reason to extend the
use of initializer lists in this direction is to get a uniform
mechanism for initialization. In particular, we don't have to worry
about whether a type is implemented as a built-in or a user-defined
type and we don't have to depart from the direct initialization to
avoid the unfortunate syntax clash between () initialization and
function declaration. For example:
X a = { v };
X b = { };
"


Steve Ward

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





Author: AlbertoBarbati@libero.it (Alberto Ganesh Barbati)
Date: Tue, 27 Mar 2007 14:42:22 GMT
Raw View
Steve Ward ha scritto:
>
> "
> 4.7.1 Aggregate initialization
>
> In line with our ideal of allowing initializer lists just about
> everywhere - and following existing rules - we can initialize a non-
> aggregate with an initializer list with 0 or 1 element. The empty
> initializer list gives value initialization. The reason to extend the
> use of initializer lists in this direction is to get a uniform
> mechanism for initialization. In particular, we don't have to worry
> about whether a type is implemented as a built-in or a user-defined
> type and we don't have to depart from the direct initialization to
> avoid the unfortunate syntax clash between () initialization and
> function declaration. For example:
> X a = { v };
> X b = { };
> "
>

Cool, so we finally have an explicit syntax for value-initialization?
But... wait... just a few paragraph below, in the same section it is said:

"A class with a generated default constructor can co-exist with
initializer list initialization. However, this would be an error:

  struct SS {
    SS() { }
    string a, b;
  };
  SS ss0 = { }; // error:"

so it seems to me that the intent of the last statement of the previous
paragraph " we don't have to worry about whether a type is implemented
as a built-in or a user-defined type" is, at least in part, defeated.
What am I missing?

Regards,

Ganesh

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