типизирование утки — C ++: доступ к члену класса с помощью метода-члена

У меня есть шаблон класса, который выглядит так:

template<int n=3> struct Vec{
double Values[n];
};

Конечно, я могу получить доступ к элементам этого класса напрямую или с помощью метода, например:

double& x(){
return Values[0];
}

Но если бы я хотел сделать более интуитивно понятный код: вместо

Vec<3> v;
v.x() = 5.2;

Я хотел бы позволить пользователю сделать это:
v.x = 5.2, Это не только каприз. Если у меня есть существующая библиотека, которая использует простые векторные структуры вида struct{double x,y,z;}Я мог бы с помощью утилитарной типизации создать мой шаблонный класс, чтобы быть эффективным в этом случае. Конечно, я мог бы (возможно, я не уверен) передать в эту библиотеку предопределенную структуру ссылок — например:
struct{double &x=v.Values[0], &y=v.Values[1], &z=v.Values[2];} но я боюсь, что это не самый простой способ получить цель.

Ах, конечно, я мог бы добавить параметры ссылочного типа в мою структуру, но это привело бы к увеличению размера элементов.

1

Решение

Вот один из способов получить тот же синтаксический эффект:

template<int n=3> struct Vec{
double Values[n];
};

template<int N> struct xyzAdapter;

template<> struct xyzAdapter<3>
{
xyzAdapter(Vec<3>& vec) : x(vec.Values[0]), y(vec.Values[1]), z(vec.Values[2]) {}

double& x;
double& y;
double& z;
};

template<int N> auto make_adapter(Vec<N>& vec)
{
return xyzAdapter<N>(vec);
}

int main()
{
Vec<3> point;
auto adapter = make_adapter(point);
adapter.x = 6;
}

Идти по другому пути не совсем так приятно. Не существует такого понятия, как массив ссылок, поэтому один из обходных путей — прибегнуть к массиву std::reference_wrapper:

#include <tuple>
#include <array>
#include <functional>
#include <iostream>

template<int N = 3> struct Vector;

template<> struct Vector<3>
{
double x, y, z;

auto as_tuple() {
return std::tie(x, y, z);
}
};

template<std::size_t...Is, class Tuple>
auto as_array(std::index_sequence<Is...>, Tuple&& t)
{
return std::array<std::reference_wrapper<double>, sizeof...(Is)> {
std::get<Is>(t)...
};
}

template<int N> auto as_array(Vector<N>& v)
{
return as_array(std::make_index_sequence<N>(), v.as_tuple());
}

int main2()
{
Vector<3> point;
point.x = 6;

auto arr = as_array(point);

for (auto ref : arr) {
std::cout << ref.get() << std::endl;
}

return 0;
}
4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]