News for hackers. Stuff that matters.
Re:C++17 creates a practical use of the backward array index... by cornstalks on Monday April 03, 2023 @04:15PM (#35430604)
> Starting in C++17, a[b] always evaluates a before evaluating b.

Okay, I'll bite. Why did C++17 specify this?

Re:C++17 creates a practical use of the backward array index... by olliej on Monday April 03, 2023 @04:23PM (#35430734)
Better question: why did C and C++ not define this as left to right (the answer is perf claims decades ago, that are not really valid now, and questionable even then).

The example

   a[b]
doesn't really exhibit the unexpected, but as I understand it

   f()->a[b()]
could evaluate as

   temp = b()
   f()->a[temp]
which it seems reasonable to consider unexpected. The lack of left to right sequencing here seems not-dissimilar to the lack of sequencing in call arguments, which was also realized to be a needless footgun and fixed.
Re:C++17 creates a practical use of the backward array index... by TremendousJudge on Monday April 03, 2023 @04:43PM (#35430997)
Half of the new features of "modern" C++ editions leave me agreeing with the change but wondering what they were thinking before. Another example: std::map::contains was introduced in C++20; why did they go decades thinking it wasn't necessary to have such an operator (instead providing only count() even though a map has unique keys), and why did they change their minds only now? Did the old guard literally die off or something?
Re:C++17 creates a practical use of the backward array index... by tubs on Monday April 03, 2023 @05:27PM (#35431519)
Problem with contains is we are now going to see more code like

    if (map.contains(foo)) {
       bob(map[foo]);
    }
over the (vastly uglier) more efficient:

   if (auto it = map.find(foo); it != map.end()) {
       bob(*it);
   }
Of course languages like C# manage this in a more elegant way with out parameters declarable at the call site.
Re:C++17 creates a practical use of the backward array index... by JonChesterfield on Monday April 03, 2023 @05:43PM (#35431717)
A pity the c++ compiler has no way to recognise calls to the c++ library in order to do rewrites like that automatically. It's CSE at the stdlib level, should definitely be possible to do that.
Re:C++17 creates a practical use of the backward array index... by eklitzke on Monday April 03, 2023 @06:38PM (#35432326)
Hard coding behavior like for the STL that seems pretty questionable, especially given that std::map and std::unordered_map have poor performance compared to other alternatives (e.g. absl::btree_map and absl::flat_hash_map, and likewise folly has better implementations).
Re:C++17 creates a practical use of the backward array index... by im3w1l on Monday April 03, 2023 @09:15PM (#35433710)
if let is such a nice way to express this

    if let Some(x) = map.get(foo) {
        bob(x)
    }
One subtle but noteworthy thing is that the idiom only mentions map by name once, which is nice if you have a very long map name, and prevents copy paste bugs where you only update one of the two mentions.
Re:C++17 creates a practical use of the backward array index... by paulddraper on Tuesday April 04, 2023 @12:26AM (#35435068)
Scala:

    for (x <- map.get(foo)) {
      bob(x)
    }

    // or

    map.get(foo).foreach(bob)

    // or

    map.get(foo) match {
      case Some(x) => bob(x)
    }
Re:C++17 creates a practical use of the backward array index... by olliej on Tuesday April 04, 2023 @02:59PM (#35444381)
This pattern exists in C++ as well. The specific issue here is that all these STL APIs are in terms of C++'s iterator model, and can't be replaced with a more modern "optional" style that allows this cleaner coding style :-/
Re:C++17 creates a practical use of the backward array index... by PaulDavisThe1st on Monday April 03, 2023 @05:09PM (#35431327)

  std::map::find (item) != map.end()  <=> std::map::contain (item)
Re:C++17 creates a practical use of the backward array index... by zimpenfish on Tuesday April 04, 2023 @04:05AM (#35436520)
I think the problem is that with `std::map::find(item)` you get the value back but you don't with `std::map::contain(item)` - which means a second lookup to actually retrieve the value, no?
Re:C++17 creates a practical use of the backward array index... by olliej on Monday April 03, 2023 @04:47PM (#35431041)
The historical lack of sequencing is because they were unsequenced in C, and C++ thus inherited it.

And yes, it does seem that there were a lot more people hell bent on resisting correcting unnecessary UB in the past than today, but they’re still around.

Re:C++17 creates a practical use of the backward array index... by TremendousJudge on Monday April 03, 2023 @04:57PM (#35431183)
I get it, but then, why change it now? (or 6 years ago I guess)
Re:C++17 creates a practical use of the backward array index... by olliej on Monday April 03, 2023 @05:02PM (#35431233)
Sorry, I had an unsaved edit above. It seems the resistance to removing unnecessary UB has reduced over the years.
Re:C++17 creates a practical use of the backward array index... by eklitzke on Monday April 03, 2023 @06:33PM (#35432249)
Because otherwise the evaluation order of the following construct is undefined, and you can get different results if you compile your code with different compilers:

  foo()[bar()];
In nearly all cases it won't matter, but it can matter if foo() and bar() have some kind of shared state (or affect each other's return values, but seriously don't do that). In general it's better to have a defined evaluation order unless there's some compelling reason not to.
Re:C++17 creates a practical use of the backward array index... by addaon on Monday April 03, 2023 @09:45PM (#35433912)
But both C and C++ are comfortable with *(foo() + bar()) having undefined evaluation order, so foo()[bar()] potentially having order-dependent results is clearly not sufficient reason for this decision...
Re:C++17 creates a practical use of the backward array index... by Dylan16807 on Monday April 03, 2023 @09:54PM (#35433961)
> In general it's better to have a defined evaluation order unless there's some compelling reason not to.

That is not the stance C++ has taken in the past, so the question of why they changed it is still unanswered.

Re:C++17 creates a practical use of the backward array index... by ynik on Tuesday April 04, 2023 @05:00AM (#35436939)
To allow for chaining. Consider a statement like:

    a.f(foo(1)).g(foo(2)).arr[foo(3)].h(foo(4));
In C++14, the foo() calls happened in unspecified order. C++17 guarantees that "a(b)" and "a[b]" evaluate "a" first, which effectively means the foo() calls will now happen in order (1 to 4).