This draft standard shows the synopsis for initializer_list
. It has no private constructor.
But two standard library implementations I have looked at, libstdc++ and libc++, both provide private constructors:
// The compiler can call a private constructor.
constexpr initializer_list(const_iterator __a, size_type __l)
: _M_array(__a), _M_len(__l) { }
_LIBCPP_ALWAYS_INLINE
_LIBCPP_CONSTEXPR_AFTER_CXX11
initializer_list(const _Ep* __b, size_t __s) _NOEXCEPT
: __begin_(__b),
__size_(__s)
{}
I believe the part where this private constructor is "implied" stems from §8.5.4/5:
An object of type
std::initializer_list<E>
is constructed from an initializer list as if the implementation allocated a temporary array of N elements of typeconst E
, where N is the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and thestd::initializer_list<E>
object is constructed to refer to that array.
So my questions are:
Is the synopsis under-specified?
Does the library need a private constructor? What does it do that the compiler can't?
The member initializer list is inserted after the constructor parameters. It begins with a colon (:), and then lists each variable to initialize along with the value for that variable separated by a comma. Note that we no longer need to do the assignments in the constructor body, since the initializer list replaces that functionality.
Private constructors are especially useful when we want to restrict the external creation of a class. Singletons, factories, and static method objects are examples of how restricting object instantiation can be useful to enforce a certain pattern. Constants classes and static method classes also dictate that a class should not be instantiable.
How to initialize Array of objects with parameterized constructors in C++ 1. Using bunch of function calls as elements of array: It’s just like normal array declaration but here we initialize... 2. Using malloc (): To avoid the call of non-parameterised constructor, use malloc () method. “malloc” or ...
It begins with a colon (:), and then lists each variable to initialize along with the value for that variable separated by a comma. Note that we no longer need to do the assignments in the constructor body, since the initializer list replaces that functionality. Also note that the initializer list does not end in a semicolon.
Is the synopsis under-specified?
No, it documents the user-facing bits of the initializer_list
class template, the parts you're actually allowed to make use of in your code. According to the synopsis the template only contains a default constructor, allowing you to create empty initializer_list
s, which is clearly not very useful. However, initializer_list<T>
is a type that depends on some magic being done by the compiler. By magic, I'm referring to §8.5.4/5 that you've quoted. This allows the following statement to be legal and compile.
std::initializer_list<int> numbers{1, 2, 3, 4}; // no such constructor in the synopsis
Here, as explained in §8.5.4/5, the compiler will create an array containing the four integers, and then initialize the initializer_list<int>
instance with either a pair of pointers (first element and one past the end element) or a pointer and length (which is what both libstdc++ and libc++ seem to do).
Once the instance has been created, your code is allowed to access all the member functions listed in the synopsis.
Does the library need a private constructor? What does it do that the compiler can't?
As the comment above the libstdc++ private constructor definition implies, the compiler is capable of emitting code that bypasses normal access control, so no, I'd say it's not essential to have that constructor. The compiler could use the default constructor to construct an empty initializer_list
instance, and then assign appropriate values to the private data members (these aren't listed in the synopsis either, but are necessary).
But why bother with that clumsiness when a private constructor provides a clean interface that the compiler can call?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With