|
From: Vidar Hasfjord on 23 Apr 2008 04:20 I've just read N2575 and welcome its proposals. N2575 takes a step back and provides a simple but brilliant programmer's perspective: the division of concerns into conversions and constructor calls. Here's some feedback. 1. In my view conversion is the important feature of the initializer list proposals. The other feature, an alternative syntax for constructor calls, I find odd and unnecessary. These syntax extensions are confusing parameter lists and initializer lists and add another idiosyncrasy to the language. I would prefer parantheses for constructor calls to always be required and to view curly brackets simply as list construction. 2. I have a gut reaction against std::initializer_list being a built- in type. A stated important goal of the proposals is to erase the special treatment of built-in types. With that in mind the introduction of a new built-in type with special treatment smells bad. The partial built-in status and library implementation is strange. Also, there is already a library type, std::tuple, that better encapsulates an initializer list. Hence it is odd that a lesser type should be preferred. My thoughts on initializer lists: An initializer list is an object of unnamed built-in tuple type. This type is a restricted incomplete type. You can do very little with it until it has manifested itself. The initializer list seeks to manifest itself by converting to another type. Unless an explicit conversion is applied the initializer list looks for a matching constructor or conversion. 1. The best match is a non-explicit unconstrained variadic constructor template. A type such as std::tuple is a perfect match as it fully describes an initializer list; i.e. the number and types of the elements. 2. Second-best match is a non-explicit constrained variadic constructor template. A type such as std::initializer_list is a good match. Concepts constrain the std::initializer_list variadic constructor template to only accept homogenous lists. Here std::initializer_list is an ordinary library type. 3. Implicit constructors and conversion operators are attempted. The initializer list looks for matching number of parameters and type according to N2575/N2531. Implicit conversions of the elements are tried if no perfect matches are found. Aside: Whether narrowing conversions should be allowed is a controversial issue. My inkling is that they should not be allowed, but that their omission should not disambiguate matches (causes surprises). E.g. {1, 1.1} should not match (int, int), but should neither select (int, double) if both are available. It should be ambiguous. How do existing uses of initializer lists fit with this view? int a [3] = {1, 2, 3.0}; This is defined to work by converting the initializer list on the right to an array using a built-in variadic constructor template for arrays. This built-in constructor handles implicit conversion. (This allows current narrowing without requiring narrowing to be the general rule.) struct A {int x; int y;} a = {1, 2.0}; This is defined to work by converting the initializer list on the right to an instance of A using a built-in constructor taking parameters (int, double). This means that the constructor call A (1, 2.0) is now allowed without declaring a constructor for A. (Again, these automatically generated constructors takes care of the narrowing issue.) In summary, the overarching ideal for a solution to initializer lists is in my view to erase the special treatment of built-in types. My benchmark: int a [] = {1, 2, 3}; // size deduced std::array <int, auto> = {1, 2, 3}; // should also work Reference: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2575.pdf Regards, Vidar Hasfjord -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Pages: 1 Prev: A Set of Questions About Console I/O and Structures... Next: exception base class |