Is providing a private constructor for initializer_list conforming?

[亡魂溺海] 提交于 2019-12-01 16:09:23

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?

The question boils down to whether an implementation may define something beyond what the standard dictated. Yes, that is possible.

Indeed §17.6.5.5 (draft n° 3797) states:

A call to a member function signature described in the C ++ standard library behaves as if the implementation declares no additional member function signatures.

Footnote 189:

189) A valid C++ program always calls the expected library member function, or one with equivalent behavior. An implementation may also define additional member functions that would otherwise not be called by a valid C++ program.

You are not allowed to call to call those additional member functions, even if they were accessible.

Regarding std::initializer_list

Does the library need a private constructor? What does it do that the compiler can't?

The standard defines what you'd expect when constructing a std::initializer_list<T> from an initializer list. The way it's done is implementation-defined and, for what said above, it may therefore call a private constructor.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!