Efficient Data Structures

Context

value, reference, const_reference

Consider the following structs to understand the problem.

struct point_soa { std::vector<int> x, y, x; };
point_soa p_soa = {{1, 2, 3}, {4, 5, 6}, {8, 9, 10}};

struct point { int x, y, z; };
point& p = { p_soa[1].x, p_soa[1].y, p_soa[1].z }; // error

struct point_reference { int& x, y, z; };
point_reference pr = { p_soa[1].x, p_soa[1].y, p_soa[1].z }; // works

pr = p_soa[1]; // we want something like this
 
We use the types "value", "reference", "const_reference" below, and a type "proxy_type" that converts between them.
 
#include <cstddef>
#include <iostream>
#include <vector>

template <typename T> using value = T;
template <typename T> using reference = T&;
template <typename T> using const_reference = const T&;

template <template <class> class F_in, template <template <class> class> class S>
struct proxy_type : S<F_in> {
template<template <class> class F_out>
operator S<F_out>() const {
auto& [x, y, z] = *this;
return {x, y, z};
}

};

template <template <class> class F, template <template <class> class> class S>
struct wrapper {
S<F> data;
proxy_type<reference, S> operator[](std::size_t i) {
auto& [x, y, z] = data;
return {x[i], y[i], z[i]};
}

proxy_type<const_reference, S> operator[](std::size_t i) const {
auto& [x, y, z] = data;
return {x[i], y[i], z[i]};
}

};

template<template <class> class F> struct S { F<int> x, y, z; };

int main() {
wrapper<std::vector, S> my_array = {{{1, 2, 3}, {4, 5, 6}, {8, 9, 10}}};

S<reference> r = my_array[1];
r.x = 42; // my_array[1] changed

S<value> v = my_array[1];
v.x = 43; // v ist just a copy, my_array[1] remains unchanged

S<const_reference> cr = my_array[1];
cr.x = 43; // error: cannot assign to const-qualified type

std::cout << cr.x << std::endl; // 42

return 0;
}