0

Left associativity is already guaranteed by C++ core semantics: R|V1|V2 is parsed as (R|V1)|V2). What if the coder wants to explicitly change the order of operations to R|(V1|V2)? Is this possible under C++23? The reason behind the question is that it simplifies defining custom range adapters:

auto myV=V1|V2|V3;
for(auto& x:R1|myV)/*..*/;
for(auto& x:R2|myV)/*..*/;

All this needs seems to be a properly constraint overload on std::views::operator|; Does such overload exist? If not, will it be added? If not, what's the rationale behind it?

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Red.Wave
  • 2,790
  • 11
  • 17
  • Unfortunately associativity of C++ operators cannot be changed, overloaded or not. – Sam Varshavchik Apr 03 '23 at 16:46
  • @SamVarshavchik , you misunderstood. I want to costumize range adapters by composition through chaining the pipe operator. And it is possible. I am asking if the standard has this feature or not? – Red.Wave Apr 03 '23 at 16:55
  • 2
    I don't believe I misunderstand. The first paragraph is pretty clear: can associativity of the `|` operator be changed? Nope. – Sam Varshavchik Apr 03 '23 at 16:56
  • @SamVarshavchik No! That's your miss-interpretation. We need a right associativity on view adapters (if you know math as much as you know C++), and it just needs another overload of `operator|`. No changes to the core, just a library tweak. – Red.Wave Apr 03 '23 at 17:26
  • @SamVarshavchik I bet you didn't look at the snippet right below the 1st paragraph. – Red.Wave Apr 03 '23 at 17:28
  • I don't... understand the question, are you asking if `R | (V1 | V2)` is valid? – Barry Apr 03 '23 at 18:01
  • @Barry, bingo! You did understand it indeed. I am sure you do have the answer. So please leave a full reply. – Red.Wave Apr 03 '23 at 18:06
  • @Barry feel free to suggest a proper edit. I am much better at C++ than English. – Red.Wave Apr 03 '23 at 18:08

1 Answers1

5

What if the coder wants to explicitly change the order of operations to R|(V1|V2)?

Then they can just write that. That is a valid expression.

The way that range adaptor closure objects are defined, there are two equivalences (C and D here are range adaptor closure objects and R is a range):

  • R | C is equivalent to C(R)
  • R | (C | D) is equivalent to R | C | D

The latter is the property that lets you write what you're asking about. For instance:

auto flat_map = [](auto f){
    return views::transform(f) | views::join;
};

vector<int> v = {1, 2, 3};
auto w = v | flat_map([](int i){ return vector<int>(i, i); }

And here w becomes the range [1, 2, 2, 3, 3, 3].

Barry
  • 286,269
  • 29
  • 621
  • 977
  • That's great. So composition of adapters is just that simple for an average programmer. All that coder needs is considering the lifetime of parameters to specific adapters. – Red.Wave Apr 03 '23 at 18:31