complete statically-typed C++ arrays

321 views
Skip to first unread message

Farid Mehrabi

unread,
Feb 24, 2017, 1:11:42 PM2/24/17
to ISO C++ Standard - Future Proposals
hi,

A first-round request for comments. Please let me know if this is worth the trouble.
I would like to see arrays as complete ,statically-typed, constexpr-able entities in C++. For backward compatibility, new array type is supposed to introduce new but simple syntax as well as semantics. Various dynamically-typed arrays could be implemented in library via [partial] erasure of type. More details could be found in the attachment.

Thanks in advance.
P0442R0.pdf

Nicol Bolas

unread,
Feb 24, 2017, 2:32:43 PM2/24/17
to ISO C++ Standard - Future Proposals
On the `initializer_list` changes: No.

`std::initializer_list` exists for one purpose: to be a way to talk to objects that are initialized with homogeneous lists of values. It is not a "magic solution for the lack of array literals;" otherwise, they'd have just used `std::array`. The point of `initializer_list` is that the implementation owns and manages the storage for the array in question.

We should not change that just because you've created a new array type. If we wanted people to create `initializer_list`s from their own arrays, then we would have made them constructible from `std::array`.

"not providing any implementation regarding its own initialization!!!" is a feature, not a bug. If you want to initialize a `vector` from a braced-init-list, it uses the `initializer_list` constructor. If you have some type, you use the range constructor.

Oh, and your `initializer_list` constructor from a "C++-array" is dangerously non-`explicit`. We don't want those just popping up; if a user creates an `initializer_list`, they need to mean it.

I'm also not sure how this proposal solves the problems you put under the heading "constexpr string/array". Because we already can have that. The problem is using them as template arguments, which leads to a number of issues. I don't see a listing of these issues or how your proposal solves them.

After all, `std::array` is a constexpr array type. It can be constexpr initialized and manipulated. But such an object cannot be used as a template argument. I fail to see what your proposed "C++-array" type provides that `std::array` does not. Obviously besides the explicit statement that your "C++-array" type can be used as a template argument; we could just as easily have a proposal that allows `std::array` to be used as a template argument.

Why do we need this language construct just to say that?

Farid Mehrabi

unread,
Dec 16, 2017, 4:37:03 PM12/16/17
to ISO C++ Standard - Future Proposals
The problem with any sort of constexpr string or array type is its literal value syntax. For arrays the appropariate literal syntax is hijacked by the initializer list. And the case with string literal is even worse.
The skewed copying semantic of arrays is another obstacle against defining any none default-constructible constexpr array/string type.
Touching old C style array semantics is imposible, so the only remaining solution is to define new builtin array with proper syntax.
About the initializer_list: the only reason for its existance is the semantics of relic C style a array that does not allow using curly-brace-enclosed values as arrays. So the only option to be able to be able to use curly-brace-enclosed values would be some magic type named initializer_list which lacked a formal implementation, hence could not be constexpr.The outcome was being unable to constexpr-initialize any array type to none-default values.
Its time for the statically sized C++ style array to claim its initialization format and take it back from the initializer_list.
Currently it is assumed that C array is constructed from initializer_list. The proposition is to consider that C array and initializer_list are both constructed from C++ array.
No existing code is broken. The initializer_list gets a verbose platform dependent formal implementation which is eventually some type(size) erasure on C++ array. This type erasure nature is usefull for iterative(none template) constructor definition of containers.
For making any array type arbitrarily constexpr constructible, one might need to initialize it with C++ array which is going to be the true decltype of curly-brace-enclosed values. In order to make it arbitrary enough though, the size of input array needs be a none-type template argument to the constructor, but if a constexpr implementation of initializer_list -in terms of C++ array- be at hand, the above bargain of constructor template is totally removed.

Nicol Bolas

unread,
Dec 16, 2017, 10:56:07 PM12/16/17
to ISO C++ Standard - Future Proposals
On Saturday, December 16, 2017 at 4:37:03 PM UTC-5, Farid Mehrabi wrote:
The problem with any sort of constexpr string or array type is its literal value syntax.

I do not see how a "literal value syntax" has anything to do with a type being `constexpr`. Equally importantly, a braced-init-list is not "literal value syntax" for an array.

For arrays the appropariate literal syntax is hijacked by the initializer list. And the case with string literal is even worse.
The skewed copying semantic of arrays is another obstacle against defining any none default-constructible constexpr array/string type.
Touching old C style array semantics is imposible, so the only remaining solution is to define new builtin array with proper syntax.



About the initializer_list: the only reason for its existance is the semantics of relic C style a array that does not allow using curly-brace-enclosed values as arrays.

Nonsense. We needed a special type because we wanted to give that type special semantics in the language. For example, [over.match.list]/1.1: the clause that causes `initializer_list` constructors to be preferred over non-initializer_list constructors.

You couldn't do that in a backwards-compatible way without creating a specialized type. And you wouldn't want to do it with a type that has some actual use like `std::array`. By creating a specific type for it, we ensure that users don't accidentally create the equivalent of an initializer-list constructor by having a type that can be constructed from `T[]` or `std::array<T>` or whatever.

So the only option to be able to be able to use curly-brace-enclosed values would be some magic type named initializer_list which lacked a formal implementation, hence could not be constexpr.The outcome was being unable to constexpr-initialize any array type to none-default values.

You keep talking about this, but you're wrong. Observe:

constexpr int arr[5] = {1, 2, 3, 4, 5};

Oh look, constexpr initialization of an array type to "none-default[sic]" values. I'll do it again:

constexpr std::array<int, 5> arr = {1, 2, 3, 4, 5};

And again:

constexpr std::initializer_list<int> arr = {1, 2, 3, 4, 5};

So what are you complaining about that you cannot do? The only things you cannot do is use them as values in template parameters. And with the spaceship operator, we seem to be moving towards being able to use more types as template parameters. There's no reason why `array<T>` or another array type would be unable to be used as such (for appropriate `T` values).

Its time for the statically sized C++ style array to claim its initialization format and take it back from the initializer_list.
Currently it is assumed that C array is constructed from initializer_list.

No, it isn't. C-style arrays cannot be initialized by objects of type `initializer_list`. This:

int arr[5] = {1, 2, 3, 4, 5};

Does not create an `initializer_list`. And you can tell because this doesn't compile:

auto il = {1, 2, 3, 4, 5};
int arr[5] = il; //Cannot construct a C-style array from an `initializer_list`

The first one is a case of aggregate initialization. No object of type `std::initializer_list` is ever created.

The proposition is to consider that C array and initializer_list are both constructed from C++ array.

No. An `initializer_list` must be created from a braced-init-list and nothing else. This type is nothing more than a necessary implementation detail of using list-initialization, and it should not be considered anything more than that.

Farid Mehrabi

unread,
Dec 17, 2017, 12:17:52 AM12/17/17
to ISO C++ Standard - Future Proposals
Your examples are showing the problem: why can you not use the array or initializer_list in as a template parameter?
Second question: what is the true type of CBLV (curly-braced-list of values) that initializes both C array and initializer_list?
Third question: why is initializer_list prefered over C array in capturing the CBLV? Well because C array is relic; nobody dare touching its complex semantics - trying to avoid breaking things. C array was a result of premature optimization. Because copying arrays was believed to be expensive and prone to stack overflow, it was defined as -so called- reference type.
Forth question: why is initializer_list declared as a library class and not a built-in type?
In any other sane language that I have ever seen, equivalent of CBLV has the array type. That includes C dialects(C#, java ...).

Bottom line is constexpr array literal needs syntax and semantic spec and I am keen to see a proper one.

Nicol Bolas

unread,
Dec 17, 2017, 10:25:04 AM12/17/17
to ISO C++ Standard - Future Proposals
On Sunday, December 17, 2017 at 12:17:52 AM UTC-5, Farid Mehrabi wrote:
Your examples are showing the problem: why can you not use the array or initializer_list in as a template parameter?

Because C++ doesn't allow any user-defined types to be template parameters, arrays or not.

Yet. With the spaceship operator in place, this is now becoming a possibility for future standards. Note that it was comparison that was one of the primary sticking points, not how you spell the array type. Nor with whether `std::array` or whatever can be `constexpr`.

Second question: what is the true type of CBLV (curly-braced-list of values) that initializes both C array and initializer_list?

Braced-init-lists do not have types. They are a grammatical construct that is used to initialize an object. Asking what type they are is roughly equivalent to asking the type of an `if`.

Third question: why is initializer_list prefered over C array in capturing the CBLV?

If you're talking about `auto` deduction, it is preferred because it makes sense. Remember: a braced-init-list is not an array; it is a C++ construct that is meant to initialize an object. An `initializer_list` is a container of a homogeneous sequence of objects which is meant to initialize an object. So if you use a braced-init-list without having a specific object in mind to initialize, it defaults to the closest thing that still retains the powers of the braced-init-list: an `initializer_list`.

As for why `initializer_list` exists, I explained that already.

Well because C array is relic; nobody dare touching its complex semantics - trying to avoid breaking things. C array was a result of premature optimization. Because copying arrays was believed to be expensive and prone to stack overflow, it was defined as -so called- reference type.
Forth question: why is initializer_list declared as a library class and not a built-in type?

Why should it be? What advantage would there be in making it a built-in type?

You also seem to forget that `initializer_list` is not a container; it is a view type. The actual array storage it references is not owned by the `initializer_list`.
 
In any other sane language that I have ever seen, equivalent of CBLV has the array type. That includes C dialects(C#, java ...).

Bottom line is constexpr array literal needs syntax and semantic spec and I am keen to see a proper one.


No, "constexpr array literal" does not need a syntax. There's no such thing. 
Reply all
Reply to author
Forward
0 new messages