Saturday, September 6, 2014

RPN List – To Standard List

The RPN List class list member was changed from QList to std::list.  The largest part of this change is due to standard lists not being indexed by a simple integer like a QList (which is implemented as an array internally), but with iterators as the standard list is a double linked list internally.

The significant parts of this change include iterating over the items in the list (changing regular indexed for loops to C++11 range-for loops) where the get item at index function was removed and access to the list's constant begin and end iterators was added; updating the RPN List class access functions for adding to or inserting into the list; and updating the INPUT command translate function to handle an iterator for inserting input parse codes into the list instead of an index.  Click Continue... for details of these changes.

[branch cpp11 commit 9bca14b4b5]

Iterating Over Lists

Since standard lists cannot be looped over with an index from 0 to the size of the list, a C++11 range-for is used.  This is similar to the foreach macro provided by Qt.  Looping over the elements of the RPN list were changed (where there is a pointer to the RPN list instance):
for (int i = 0; i < rpnList->count(); i++) {    ← old
    RpnItemPtr rpnItem = rpnList->at(i);
    ...

for (RpnItemPtr rpnItem : *rpnList) {          
← new
    ...
The loop variable is changed from an index to the type of the actual item in the list.  Previously the at function was used to get an item from the list, but now the item is the loop variable.  The type of the loop variable could be the new C++11 auto type instead of RpnItemPtr to let the compiler determine the type, however, the completion feature Qt Creator no longer works on the loop variable to display the available member functions.  Therefore, the auto type is used sparingly.  (Maybe a future version of Qt Creator will be able to detect actual type with auto.)

Beside changing the various iteration loops as described, these additional changes were made:
  • The at access function was removed since it no longer is applicable.
  • In order to iterator over an RPN list, the RPN List class needs to provide the constant begin and end iterators to the list member, so access functions for these were added.
  • The text function previously used the index variable to detect when not the first time through the loop.  This was changed to check if the string stream is not empty.
  • The equality operator function previously used the index variable to access the items from both lists.  The range-for only has a variable for the member items, so an other iterator variable was added to iterator over the other list using iterator increment at the end of the loop.  Since no members of the other iterator are used, the auto type was used for this variable.

Appending List Items

The C++11 standard container classes provide new emplace functions (emplace, emplace back).  These are similar to the push functions (Qt's append) except that they do an in-place construction of the item being added.  Their arguments are the arguments for the constructor of the new item.  This is advantageous when a new element needs to be created.  With the push functions, a temporary element needs to be created first, then copied.  Consider the old and new versions of the append function:
RpnItemPtr rpnItem = RpnItemPtr{new RpnItem(token, attached)};     ← old
QList<RpnItemPtr>::append(rpnItem);
return rpnItem;

emplace_back(RpnItemPtr{new RpnItem{token, attached}});            ← new
return back();
In the old version, the new item is first created, then it is appended to the list, and finally the item (a pointer to) is returned.  The new version simply constructs the new element in-place.  Had push_back() been used instead of emplace_back() a temporary element would have been created and then moved into the list.  The emplace saves a little bit of work internally.  The back() function provides access to the element just added.  The emplace was already used in the construction of the attached RPN items vector.

Inserting List Items

Previously items were inserted into a QList with a simple index value (since the list is an array internally).  Standard lists use an iterator to insert an item.  The INPUT command translate is currently the only routine that inserts items into the list.  It inserts input parse codes into the list just before the input begin code as each variable is translated.  This was accomplished by getting the size of the list just before adding the input begin code, which was then used as the index to insert parse codes.

For standard lists, an iterator needed to be obtained that points to the item just added.  This was accomplished by using the standard list emplace function, which returns an iterator to the item just inserted.  The emplace function is similar to the insert function, except it does an in-place construction.

The input parse codes are inserted in reverse order (which will be more optimal at run-time).  When using an index for insertion, the index value did not change for each insertion, so each parse code was inserted before the last parse code inserted.  However, when inserting with an iterator, the iterator continues to point to the input begin code, therefore, a new iterator needs to be obtained to each parse code inserted into the list.

The index argument of the insert function of the RPN List class was changed to an iterator, which is passed to the standard list emplace function.  The iterator returned is returned from the insert function.  A new append iterator function was added to append an item and return an iterator to the item.  This function simply calls the insert function passing the end iterator so that the item is inserted to the end of the list.  A corresponding output append iterator access function was added to the Translator class (which is used by the INPUT translate routine to append the input begin code).

No comments:

Post a Comment

All comments and feedback welcomed, whether positive or negative.
(Anonymous comments are allowed, but comments with URL links or unrelated comments will be removed.)