Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is providing a private constructor for initializer_list conforming?

This draft standard shows the synopsis for initializer_list. It has no private constructor.

http://i.stack.imgur.com/5bc61.png

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 type const 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 the std::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?

like image 830
user4700874 Avatar asked Mar 22 '15 21:03

user4700874


People also ask

How to use the member initializer list in a constructor?

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.

When to use private constructors?

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++?

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

How do you initialize a variable in a constructor?

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.


1 Answers

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_lists, 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?

like image 200
Praetorian Avatar answered Oct 23 '22 11:10

Praetorian