Brace-enclosed

0 views
Skip to first unread message

Tamela

unread,
Aug 5, 2024, 1:09:28 AM8/5/24
to migneitofil
Ive looked up many sources online, and it seems there is not a lot of information in the topic, but came up to things such as FastArduino: initializer list, and Arduino STL: Initializer list. Giving me hopes that it is actually possible. (I can't use those libraries, because they lack the build system generation tools on the library I am developing, they also lack on customizability, and also as a good learning experience)

I have already implemented a custom cpstd::initializer_list and constructor that should handle this, but the issue persists. Is there something specific to the Arduino environment that could be causing this issue?


While reading the error log, I noticed that std::initializer_list constructor has two parameters, a pointer to the data, and also a variable telling the length of the braced enclosed list, however I noticed that the list ends up casting to a single parameter, hence having no possible constructor to call


What could be causing this issue, and how can I resolve it to initialize cpstd::vector using brace-enclosed initializer lists in the Arduino environment? I think the main issue is with boards that have no STL support. (i.e. AVR based boards)


I've came to the conclusion that it will not be possible to create such constructors/operators due to compiler limitations, I think I've tried anything that came to mind. But I don't want to give up on this without knowing if there is a workaround.


So I have been messing around with the minimal example code and found a working solution, I'll post the solution just in case someone finds themselves having the same issue on the future, the only downside is that it feels a bit hacky to my taste, I still wonder if there is a better solution. And would gratly appreciate any feedback.


Considering the sequence of initializer clauses, and the sequence of aggregate elements initially formed as the sequence of elements of the aggregate being initialized and potentially modified as described below:


The analysis is complete when all initializer clauses have been exhausted. If any initializer clause remains that does not appertain to an element of the aggregate or one of its subaggregates, the program is ill-formed.


The number of elements in an array of unknown bound initialized with a brace-enclosed initializer list is the number of explicitly initialized elements of the array. An array of unknown bound cannot be initialized with .


Each direct non-static data member named by the designated initializer is initialized from the corresponding brace-or-equals initializer that follows the designator. Narrowing conversions are prohibited.


For a non-union aggregate, elements for which a designated initializer is not provided are initialized the same as described above for when the number of initializer clauses is less than the number of members (default member initializers where provided, empty list-initialization otherwise):


Note: out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays are all supported in the C programming language, but are not allowed in C++.


Until C++11, aggregate initialization could only be used in variable definition, and could not be used in a constructor initializer list, a new-expression, or temporary object creation due to syntax restrictions.


[CWG2149] points out an inconsistency inthe wording with respect to array lengths inferred from bracedinitializer lists in the presence of brace elision. The wording haschanged since the issue was raised, but the essence of the issueremains. The standard first states that the length of an array ofunknown bound is the same as the number of elements in the initializerlist, but then describes the rules for brace elision, in which someelements are used to initialize subobjects of aggregate members, suchthat there is not a one-to-one mapping of initializer list elements toarray elements. Similarly, aggregate initialization from a bracedinitializer list is supposed to explicitly initialize a number ofaggregate elements equal to the length of the list, which is notpossible in the presence of brace elision.


This paper aims to resolve the core issue by clarifying the rules forbrace elision to match user expectations and the behavior of existingcompilers. The intent is to better describe the existing design withoutintroducing any evolutionary changes.


(4.2)Otherwise, if theinitializer list is a brace-encloseddesignated-initializer-list, the element is copy-initialized from thecorresponding initializer-clause or is initializedwith the brace-or-equal-initializer of the correspondingdesignated-initializer-clause. If that initializer is of theform assignment-expressionor= assignment-expressionand a narrowing conversion (9.4.5[dcl.init.list]) isrequired to convert the expression, the program is ill-formed.


(4.3)Otherwise, the initializerlist is a brace-enclosed initializer-list. If aninitializer-clause appertains to the aggregate element, thenthe aggregate element is copy-initialized from theinitializer-clause. Otherwise, the aggregate element iscopy-initialized from a brace-enclosed initializer-listconsisting of all of the initializer-clauses that appertain tosubobjects of the aggregate element, in the order ofappearance.


10 An The number of elements (9.3.4.5[dcl.array]) inan array of unknown bound initialized with a brace-enclosedinitializer-list containingninitializer-clauses is defined as havingn elements(9.3.4.5[dcl.array])the number of explicitlyinitialized elements of the array.


[ Note: A default member initializer does notdetermine the bound for a member array of unknown bound. Since thedefault member initializer is ignored if a suitablemem-initializer is present (11.9.3[class.base.init]),the default member initializer is not considered to initialize the arrayof unknown bound.


14 If anaggregate class C contains asubaggregate element e with noelements, the initializer-clause fore shall not be omitted from aninitializer-list for an object of typeC unless theinitializer-clauses for all elements ofC followinge are also omitted.


16 Bracescan be elided in an initializer-list as follows. If theinitializer-list begins with a left brace, then the succeedingcomma-separated list of initializer-clauses initializes theelements of a subaggregate; it is erroneous for there to be moreinitializer-clauses than elements. If, however, theinitializer-list for a subaggregate does not begin with a leftbrace, then only enough initializer-clauses from the list aretaken to initialize the elements of the subaggregate; any remaininginitializer-clauses are left to initialize the next element ofthe aggregate of which the current subaggregate is an element.


14 Eachinitializer-clause in a brace-enclosedinitializer-list is said to appertain to an element ofthe aggregate being initialized or to an element of one of itssubaggregates. Considering the sequence of initializer-clauses,and the sequence of aggregate elements initially formed as the sequenceof elements of the aggregate being initialized and potentially modifiedas described below, each initializer-clause appertains to thecorresponding aggregate element if


Otherwise, the aggregate element is an aggregate and thatsubaggregate is replaced in the list of aggregate elements by thesequence of its own aggregate elements, and the appertainment analysisresumes with the first such element and the sameinitializer-clause.


15 Allimplicit type conversions (7.3[conv]) are considered wheninitializing the element with an assignment-expression. If theassignment-expression can initialize an element, the element isinitialized. Otherwise, if the element is itself a subaggregate, braceelision is assumed and the assignment-expression is consideredfor the initialization of the first element of the subaggregate.


The basic form for a UUID string is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx where each x is a hexadecimal digit, case-insensitive. (I personally prefer all-uppercase.) All of the parsing functions under discussion use this basic form as their basis of exploration. Some functions expect the basic form to be enclosed in curly braces; others do not.


Slightly more complicated is CLSIDFromString. In addition to accepting a brace-enclosed string (which is treated as a GUID), it also accepts a ProgId. In the ProgId case, it returns the CLSID associated with that ProgId. For example, if you ask for Paint.Picture, it will return the GUID D3E34B21-9D75-101A-8C3D-00AA001A1652. As with the other functions, passing NULL is valid and results in GUID_NULL.


Background:

There are lots of tuple operations where arrays of values and flags are being passed.

Typically these arrays are being previously initialised 0/false by memset.

By modifying code to use C99 designated initialiser syntax [1], most of these memsets can become redundant.

Actually, this mechanism is already being used in some of the existing OSS code. This patch/proposal just propagates the same idea to all other similar places I could find.


---

[1] REF C99 [$6.7.8/21] If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate,

or fewer characters in a string literal used to initialize an array of known size than there are elements in the array,

the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration

3a8082e126
Reply all
Reply to author
Forward
0 new messages