-
-
Notifications
You must be signed in to change notification settings - Fork 993
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
Fix error: control may reach end of non-void lambda #2099
Conversation
Hmm, while this does logically fix the error, I wonder if perhaps the proper approach in that case would be "don't sort at all"... |
Your call. I considered throwing, too. |
If by_name and by_relation are both omitted, behave as if both were given: sort first by relation then by name.
Does returning true not assert on MSVC debug builds? |
Neither Release nor Debug for MSVC issued a message for falling through a lambda. Current this week; don't know if it's a regression from older versions. |
I was referring to the fact that a comparator always returning true is not a "proper" comparator which might cause MSVC debug libs to assert when it discovers that a<b is the same as b<a. |
Returning To remove this dependence on an implementation detail, and to make the code a bit cleaner/clearer, it might be a good idea to stick In addition, if a default case is still desired, it really should return |
This is precisely what I was worried about, as the MSVC debug libraries assert if it's not. |
Hmm... would the lack of asserts being triggered reflect a lack of testing, or would it reflect difficulty hitting the problematic case? The On a related note, the commit that was mentioned earlier (4c9eab7) removed a comment asking if the current approach was the simplest way to represent the sorting method. I would answer that with a "no" after coming up with the following: std::sort(users_sorted_.begin(), users_sorted_.end(), [&](const user_info* u1, const user_info* u2) {
// Check each requested sort. If equivalent by that sort, fall down to the next sort.
if ( by_relation ) {
if ( u1->relation != u2->relation )
return u1->relation < u2->relation;
}
if ( by_name ) {
int icomp = translation::icompare(u1->name, u2->name);
if ( icomp != 0 )
return icomp < 0;
}
// All sorts compared equivalent, so u1 is not less than u2.
return false;
}); I did not test this, nor even check to see if it compiles, my apologies. (At some point the Wesnoth code base starting requiring package updates that are not readily available for my flavor of Linux, and I have not taken the time to update them manually.) To my eye, it looks like this should work, and it avoids a bit of code duplication. |
Knowing @GregoryLundberg I'd be more inclined to believe difficulty hitting a problematic case over lack of testing. |
I have problems with the original logic. It worked but it sure fails the sniff-test as can be seen by the amount of talk a one-liner has generated. As I said, I would have preferred to throw but the original code returned so I went with that. |
@GregoryLundberg Why would you prefer throwing? |
For the record, I’m th one who originally wrot that code in the first place (including the comment about how succinct it was) and really, the only thing I was trying to do was get it as close to a 1-line return statement as possible. I’m also not even sure if what I wrote correctly translated the original logic that was there (it made use of sorting helper structs). Someone would need to check the log for that file. |
It’s very possible I screwed something up since I didn’t (and still don’t) fully understand the intricacies of the sort function. |
@Vultraz It looks like the original lambda reflected the helper struct logic except on two points. First, the lambda no longer casts an enum (the relation) to an int before comparing with I would not put so much value on having a 1-line return statement. There is value in being succinct, but squashing a lot of logic into a single expression does not necessarily result in more optimized executable code. More likely, it results in source code that is harder for humans to read and maintain. For example, the line in question was As another example, it looks like this attempt to have a 1-line return statement actually resulted in more complex code. I can see how the line in question might have originated as an attempt to handle all cases in a 1-line return statement. Then you realized that it would not handle the |
That would be optimal, except it is possible for both flags to be true since this is controlled by two toggle buttons in the MP Lobby UI. However, I’ve been considering simply making sorted-by-name implicit and only leaving the sort-by-relation option, so that might render all of this invalid. |
Right, but the exception is irrelevant. Putting that line in context: if(by_name && by_relation) {
return u1->relation < u2->relation || (u1->relation == u2->relation && u1->name < u2->name);
}
return (by_name && u1->name < u2->name) || (by_relation && u1->relation < u2->relation); Once you broke out the earlier case, the remaining cases could be handled in a simpler manner, but you failed to see that, presumably because you were still hung up on having a 1-line return statement. |
Minor point: "render all of this moot", not "invalid". |
Committed that in 29e7e57 |
If by_name and by_relation are both omitted, behave as if both were given: sort first by relation then by name.