4

I have a std::vector<T> vec where consecutive blocks of 3 elements are of interest. For ease of processing, I'd like to extract such elements. Currently, the code looks like:

const T& a = vec[i];
const T& b = vec[i + 1];
const T& c = vec[i + 2];

I'd like to use a structured binding to compress the extraction of a, b, c to a single line.

A simple option would be something along the lines of:

std::tuple<T, T, T> getElement(int i) {
    return std::make_tuple(vec[i], vec[i+1], vec[i+2]);
}

// ...
auto [a, b, c] = getElement(j);

The problem is that I would like to avoid useless copying of data. I'm not sure, but it seems that the vector elements will be copied here into the tuple. Would using std::tuple<T&, T&, T&> be an option?

Paul92
  • 8,827
  • 1
  • 23
  • 37

1 Answers1

5

Would using std::tuple<T&, T&, T&> be an option?

It would, and there's already a utility for it in the standard library: std::tie. It accepts an arbitrary number of references (to different types even), and returns a tuple of references to the same objects. So your use case can be condensed to

auto getElement(int i) {
    return std::tie(vec[i], vec[i+1], vec[i+2]);
}
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • Just to fill in... `std::tie` is pure gold. – Ted Lyngmo Oct 04 '19 at 23:37
  • Really nice! Is there any way to get rid of the auto return type and specify something more...concrete? – Paul92 Oct 05 '19 at 23:04
  • @Paul92 - You know the type of the objects, so you can specify the tuple of references if you wish. But personally, I consider `auto` more than justified here. – StoryTeller - Unslander Monica Oct 05 '19 at 23:11
  • You're right - the return tuple was having const references, I tried with a tuple of references and got an error which confused me. For a short getter like this, I would agree. But the function is a bit larger and goes into a cpp. I think a declaration like `auto getElement(int i);` in a class is a bit confusing. – Paul92 Oct 05 '19 at 23:21