-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
Transform classic loops to range-based for loops in module common #2838
Transform classic loops to range-based for loops in module common #2838
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this pull request some loops take auto
variable by reference, and some by value. In the latter cases it means a useless copy. Of course, one may argue that for int
or float
this does not matter. True, but for complex types there is a performance penalty. In my opinion, is easier to just stick with the following rule of thumb: use const auto&
in range-for loops by default, drop const
if need to modify the contents. This way the code is more uniform and we don't need to think whether the type in question is complex or primitive.
Changes are based on the result of run-clang-tidy -header-filter='.*' -checks='-*,modernize-loop-convert' -fix
14c3c75
to
b8aba3a
Compare
In case I missed sth., tell me. |
@taketwo reference on a primitive has no benefit, thats why I don't use it there. Furthermore I don't use auto for primitive data types. This makes even sense if we wan't to respect this: #2731 (comment) (MinTypeNameLength => so |
This is true. But it also does not have deficit.
Why? For me, the most important thing about So @SergioRAgostinho thoughts? |
It has: I have to adjust automated adjusted code of clang-tidy ;) But for real, there is a small difference for the CPU:
True and wrong. |
I am more strict than both of you and usually just use auto for iterators and lambda types because I don't like to not know which type I'm looking at in most cases. I would prefer to transition very conservatively to auto and only use in these two uses cases I mentioned.
I'm just getting concerned over the lack of consistency :/ |
This decision is done by clang-tidy automatically. I just add a lot of
There was only one loop and this was a loop over |
@SunBlack thanks for the explanation. I understand your points but disagree.
Well, let's have a Gedankenexperiment here. Suppose you read code and see a loop for (const int& index : indices) Questions: 1) what is the type of indices? 2) should you expect/check for invalid (-1) indices? My claim is that no, you can not be sure that the type of indices is
Not necessarily, there may be a legal non-narrowing conversion from the actual type to the type you used in the loop. In this case compiler will not complain.
I don't think so. By using Scott Meyers in his "Effective Modern C++" recommends to prefer Finally, regarding the references:
Depends on the viewpoint. Compiler will do the right thing anyway, and for me it less complex to use reference always (no-brainer!), compared to thinking every time whether the type is primitive or not. |
I think it's a good idea to replace index based or iterator based for loops into range based for loops, but I don't think it's a good idea to use auto simply because there isn't an easy way to figure out immediately what the type is that we are looping through. For implicit type casts it should be avoided anyways, otherwise we are asking for bugs for ourselves, I would argue that auto potentially makes it harder to discover the problem. I also think if it's a primitive type that we are looping through it should by value, for non primitive type it should be by reference. |
Thanks for joining the discussion.
Could you give any pragmatic reason for this distinction? Also, let's clarify the language here, what exactly is "primitive type". Is this a built-in type (e.g. |
Yes I am referring to built-in types like ‘int’, ‘float’. To be honest this principle is based on copying built-in types are cheaper than indirect addressing and oppositely for non built-in types. However I understand that this principle is probably not applicable anymore for modern compilers so in the end it comes down to personal preferences. If we want to do const reference for all types in range for loops, for consistency purposes, should we also replace all pass by values in functions to pass by const references? |
That would be a rather big endeavor with no apparent benefits. Besides, it will break user code that derives from our classes and overrides affected functions. So this is out of question IMHO. As for the Speaking of |
Just to be clear, the idea is: free for all. Not even imposing auto on iterators? I have the impression we all agreed on iterators without auto being evil. |
It's hard for me to imagine someone will contribute code with non- If you guys can agree on a list of cases where |
I haven't reviewed all of the transition PRs, but I've seen enough inconsistent usage of references, Please do comment if there are any concerns or disagreement with this. |
I already let a couple slip through under the radar then :/ My apologies. I'll enforce the proposal from now on. |
I'm currently in vacation. But maybe you can already update style guide with all rules when use auto, const reference, ... (in loops and in general) |
91066c3
to
7fea1c0
Compare
Changes are based on the result of run-clang-tidy -header-filter='.' -checks='-,modernize-loop-convert' -fix