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.

### 906. `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 type `E`, 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 type `const 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:

1. In 17.10 [support.initlist]/p.1 replace in "header `<initializer_list>` synopsis" the constraint "`ObjectType`" in the template parameter list by the constraint "`ValueType`".