This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD Concepts status.
ObjectType
is the wrong concept to constrain initializer_list
Section: 17.10 [support.initlist] Status: NAD Concepts Submitter: Daniel Krügler Opened: 2008-09-26 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [support.initlist].
View all other issues in [support.initlist].
View all issues with NAD Concepts status.
Discussion:
The currently proposed constraint on initializer_list
's element type
E
is that is has to meet ObjectType
. This is an underspecification,
because both core language and library part of initializer_list
make clear, that it references an implicitly allocated array:
9.4.5 [dcl.init.list]/4:
When an initializer list is implicitly converted to a
std::initializer_list<E>
, the object passed is constructed as if the implementation allocated an array of N elements of typeE
, where N is the number of elements in the initializer list.[..]
17.10 [support.initlist]/2.
An object of type
initializer_list<E>
provides access to an array of objects of typeconst E
.[..]
Therefore, E
needs to fulfill concept ValueType
(thus excluding
abstract class types). This stricter requirement should be added
to prevent deep instantiation errors known from the bad old times,
as shown in the following example:
// Header A: (Should concept-check even in stand-alone modus) template <DefaultConstructible T> requires MoveConstructible<T> void generate_and_do_3(T a) { std::initializer_list<T> list{T(), std::move(a), T()}; ... } void do_more(); void do_more_or_less(); template <DefaultConstructible T> requires MoveConstructible<T> void more_generate_3() { do_more(); generate_and_do_3(T()); } template <DefaultConstructible T> requires MoveConstructible<T> void something_and_generate_3() { do_more_or_less(); more_generate_3(); } // Test.cpp #include "A.h" class Abstract { public: virtual ~Abstract(); virtual void foo() = 0; // abstract type Abstract(Abstract&&){} // MoveConstructible Abstract(){} // DefaultConstructible }; int main() { // The restricted template *accepts* the argument, but // causes a deep instantiation error in the internal function // generate_and_do_3: something_and_generate_3<Abstract>(); }
The proposed stricter constraint does not minimize the aim to
support more general containers for which ObjectType
would be
sufficient. If such an extended container (lets assume it's still a
class template) provides a constructor that accepts an initializer_list
only this constructor would need to be restricted on ValueType
:
template<ObjectType T> class ExtContainer { public: requires ValueType<T> ExtContainer(std::initializer_list<T>); ... };
[ Batavia (2009-05): ]
Move to Tentatively Ready.
[ 2009-07 Frankfurt: ]
Need to look at again without concepts.
Proposed resolution:
<initializer_list>
synopsis"
the constraint "ObjectType
" in the template parameter list by the
constraint "ValueType
".