0

Imagine the following situation:

class C {
  public:
  C(std::vector<int> data): data(data) {}
  C sub_structure(std::vector<size_t> indices){
    std::vector<int> result;
    for(auto i : indices)
      result.push_back(data[i]); // ***
    return C(result);
  }
  std::vector<int> data;
};
C f(){
  ...
}
...
C c = f().sub_structure(...);

I guess in the line marked ***, copies of the elements of data are made, altough sub_structure is called on an object that's about to be destroyed.

If my call was something like sub_structure(f(), ...), I could overload sub_structure by rvalue reference; however, as a class method, I'm not aware how to do that, basically based on if *this is an rvalue reference.

Is such a behaviour possible without resorting to global functions?

Bubaya
  • 615
  • 3
  • 13
  • 1
    You never use `data` in `sub_structure`, is this a typo? – perivesta May 09 '22 at 12:17
  • For what it's worth, since you mentioned the line with `***` copying, when you call `sub_structure`, you are making a copy of the vector you pass into it. You then copy every value again into a new vector called `result` (this time going from an unsigned type `size_t` to a signed (and generally smaller on 64-bit) type `int`). You then call the `C` constructor, which passes the vector as a copy. It then copies the vector into the `data` vector. Lots and lots of copies happening here. – ChrisMM May 09 '22 at 12:20
  • @ChrisMM • "I just like to copy, copying's my favorite." — Buddy the Elf (paraphrased) – Eljay May 09 '22 at 13:00
  • @ago: yes, sorry. I meant to use `data`. – Bubaya May 09 '22 at 13:43

1 Answers1

3

If my call was something like sub_structure(f(), ...), I could overload sub_structure by rvalue reference; however, as a class method, I'm not aware how to do that, basically based on if *this is an rvalue reference.

Do you mean overloading on value category? Not sure if this is what you mean, but if get your problem correctly, I'd go this way:

struct S
{
    std::vector<int> data;
    S doStuff() &&
    {
        std::cout << "rvalue\n";
        return {std::move(data)};
    }

    S doStuff() const&
    {
        std::cout << "const lvalue\n";
        return {data};
    } 
};

Demo https://godbolt.org/z/5c89edMKv

This is by no means exhaustive, one can easily return e.g reference to const *this on the const& overload, copy on non-const etc.

alagner
  • 3,448
  • 1
  • 13
  • 25
  • I believe this is what OP wants. See also https://stackoverflow.com/a/28026410/10362622 – perivesta May 09 '22 at 12:27
  • @perivesta Yes, indeed. Didn't know about these qualifiers, sorry for making you have to interpret my error. – Bubaya May 09 '22 at 13:45