Title
ObjectType is the wrong concept to constrain initializer_list
Status
nad concepts
Section
[support.initlist]
Submitter
Daniel Krügler

Created on 2008-09-26.00:00:00 last changed 163 months ago

Messages

Date: 2010-10-21.18:28:33

Proposed resolution:

  1. In [support.initlist]/p.1 replace in "header <initializer_list> synopsis" the constraint "ObjectType" in the template parameter list by the constraint "ValueType".
Date: 2010-10-21.18:28:33

[ 2009-07 Frankfurt: ]

Need to look at again without concepts.

Date: 2010-10-21.18:28:33

[ Batavia (2009-05): ]

Move to Tentatively Ready.

Date: 2008-09-26.00:00:00

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:

[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.[..]

[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>);
  ...
};
History
Date User Action Args
2010-10-21 18:28:33adminsetmessages: + msg4307
2010-10-21 18:28:33adminsetmessages: + msg4306
2010-10-21 18:28:33adminsetmessages: + msg4305
2008-09-26 00:00:00admincreate