New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR for Modernizing for C++11: replacing instances of SmallVector #6817

Open
wants to merge 30 commits into
base: master
from

Conversation

Projects
None yet
5 participants
@M3Henry
Copy link

M3Henry commented Jun 6, 2018

After discussions on IRC about modernising the code to make it easier to work on, replacing non time-critical instances of SmallVector<T,S> with std::vector was deemed more practical than making SmallVector STL-like.

This allows use of range-based for loops and STL algorithms to improve expressiveness in the code base.

No changes to functionality have been made.

#6649

M3Henry added some commits Dec 30, 2017

@M3Henry M3Henry force-pushed the M3Henry:c++11 branch from edde5ab to 072d1b9 Jun 6, 2018

@LordAro

This comment has been minimized.

Copy link
Member

LordAro commented Jun 6, 2018

Some build system changes will be needed to enforce c++11/14

@nielsmh

This comment has been minimized.

Copy link
Contributor

nielsmh commented Jun 23, 2018

LinkGraphJob::NodeAnnotationVector and GUIBridgeList (in bridge_gui.cpp) are both vectors of non-POD data types so those two are the real important ones to fix.

The former does get fixed by these changes, but GUIBridgeList does not, and from my cursory check it might be more complex to fix that one. The reason the contained data is non-POD is because of the inclusion of Money fields, that type has custom constructors which makes it non-POD.

@TrueBrain
Copy link
Member

TrueBrain left a comment

Sorry for the slow responses; we have not forgotten about this PR. I did a fast pass on the code, and "it looks fine". The main issue with patches like this is of course that reviewing takes a bit of time ;)

As mentioned earlier, it would also need some changes to the configure system, as it should detect if the used compiler can handle C++11, and warn if not. Otherwise we will have a bug-tracker full of the same error in no time :)

So please bare with us while we prepare for modern standards ;)

@@ -102,7 +102,18 @@ static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // GE
if (ifa->ifa_broadaddr->sa_family != AF_INET) continue;

NetworkAddress addr(ifa->ifa_broadaddr, sizeof(sockaddr));
if (!broadcast->Contains(addr)) *broadcast->Append() = addr;
//if (!broadcast->Contains(addr)) *broadcast->Append() = addr;

This comment has been minimized.

@TrueBrain

TrueBrain Jul 22, 2018

Member

I feel that this was by accident?

This comment has been minimized.

@M3Henry

M3Henry Jul 27, 2018

The removal was intentional, lines 108-116 replace it, but I shouldn't have left it commented out.
TBH the following would be much better than a hand rolled loop.

if (broadcast->end() == std::find(broadcast->begin(), broadcast->end(), addr)
    broadcast->push_back(addr);
@M3Henry

This comment has been minimized.

Copy link

M3Henry commented Jul 27, 2018

@TrueBrain If the intention is to keep modernizing the code, then I can go over this patch series and do it properly. Looking back on this, it doesn't seem I put forward my best.

@M3Henry M3Henry closed this Jul 27, 2018

@M3Henry M3Henry reopened this Jul 27, 2018

@LordAro
Copy link
Member

LordAro left a comment

First pass at an actual review, mostly codestyle related.

Firstly, great job on actually getting this done and working - it's a huge amount of effort (I tried SmallMap once, I gave up pretty quickly)

However, if I'm honest, I'm not sure this will ever get merged in its current form. There are just too many separate changes all bundled together. It would be better if it were a separate commit per change, rather than per file/type. Something like a commit to add new adapter functions, then one that actually converts types & functions (huge commit, but fundamentally quite simple to read through), then followed by a few commits that "neaten" usage (for loops, auto, etc)

Couple general comments:

  • Usage of and, or & not instead of &&, || & !
  • Lots of uses of auto here. Its desired usage in OTTD is yet to be formalised, but IMO it should only be used when the type of the variable doesn't matter, or if the typename has already been stated somewhere nearby. There's a few places in which that's not happened
@@ -7,14 +7,131 @@
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/

/** @file smallvec_type.hpp Simple vector class that allows allocating an item without the need to copy this->data needlessly. */
/** @file smallvec_type.hpp Simple vector class that allows allocating an item without the need to copy this->data needlessly.

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

text should be on a separate line, to preserve alignment

(applies to lots of functions)

* @tparam T the contained type of the vector
*/
template <typename T>
typename std::vector<T>::const_iterator Find(const std::vector<T>& vec, const T& elem) {

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

opening brace of a function should be on a newline

(applies to various functions)

* @param vec the vector to be searched
* @param elem the element to search for
* @tparam T the contained type of the vector
*/

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

missing @return doxygen command

(applies to various functions)

@@ -77,7 +77,7 @@ static inline int32 BigMulS(const int32 a, const int32 b, const uint8 shift)
return (int32)((int64)a * (int64)b >> shift);
}

typedef SmallVector<Industry *, 16> SmallIndustryList;
using SmallIndustryList = std::vector<Industry *> ;

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

extra space before ;

@@ -397,7 +397,7 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c
{
SortingBits order = _savegame_sort_order;
_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
QSortT(file_list.files.Begin(), file_list.files.Length(), CompareFiosItems);
QSortT(file_list.files.data(), file_list.Length(), CompareFiosItems);

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

It's a bit more work involved, but since you're converting some stuff in this PR other than just converting SmallVector, perhaps converting to use std::sort would be a good idea as well

Alternatively, it should be a separate PR (along with the various other changes in this PR) :)

This comment has been minimized.

@M3Henry

M3Henry Sep 19, 2018

I agree that the standard algorithms would be ideal where applicable, a seperate PR would make most sense.

/** Get the end of the content inf iterator. */
ConstContentIterator End() const { return this->infos.End(); }
ConstContentIterator End() const { return this->infos.end(); }

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

This looks like another class that could be refactored to be "better", instead of reimplementing a load of std::vector functions

}
else ++ts;

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

braces required here

for (i = 0; i < _text_effects.Length(); i++) {
if (_text_effects[i].string_id == INVALID_STRING_ID) break;
auto it = _text_effects.begin();
for (; it < _text_effects.end(); ++it) {

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

could probably be merged onto a single line

This comment has been minimized.

@M3Henry

M3Henry Sep 19, 2018

it needed to persist beyond the scope of the for loop. However, this is basically std::find_if, so I would re-write it with that instead.

w->lateness_counter = 0;
ClrBit(w->vehicle_flags, VF_TIMETABLE_STARTED);
/* Do multiplication, then division to reduce rounding errors. */
w->timetable_start = start_date + idx * total_duration / num_vehs / DAY_TICKS;
w->timetable_start = start_date + idx++ * total_duration / num_vehs / DAY_TICKS;

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

idx++ in the middle is a bit scary, should probably be in a separate statement

* @tparam T the contained type of the vector
*/
template <typename T>
void Reset(std::vector<T>& vec) {

This comment has been minimized.

@LordAro

LordAro Sep 19, 2018

Member

pretty sure this function isn't necessary - can be replaced with a clear() - the capacity reduction was just due to how the allocations worked

This comment has been minimized.

@M3Henry

M3Henry Sep 20, 2018

It may be a good idea to keep the capacity reduction where it is used in case that behavior is desired.
According to cppreference: "Leaves the capacity() of the vector unchanged"

@M3Henry

This comment has been minimized.

Copy link

M3Henry commented Sep 19, 2018

@LordAro
Rather than doing once large PR for a bunch of types at once, would it make more sense to submit one PR per type and do a proper conversion using standard algorithms with each one? (To avoid a PR flood I'd submit the next PR once the previous one is accepted)

@TrueBrain

This comment has been minimized.

Copy link
Member

TrueBrain commented Jan 5, 2019

We recently switched from Jenkins as CI to Azure Pipelines as CI. This means you need to rebase before this Pull Request will pass its checks. Sorry for the troubles! (might not be applicable to this PR)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment