2016-12-21 2 views
1

У меня есть класс шаблона, который выглядит следующим образом:C++: член Access класса член-подобный метод

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];}, но я боюсь, что это не самый простой способ получить цель.

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

+0

почему вы думаете, что массив будет любой более эффективной, что дискретная переменная доступа? –

+0

Если у вас есть способ шаблона различного количества дискретных переменных, я хочу знать его :) – Ch3shire

+1

Возможно, вы ищете std :: tuple <...> как шаблон. Вы можете получить элементы кортежа с помощью std :: get < INDEX > и установить их с помощью std :: tie и т. Д.? – JimmyNJ

ответ

4

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

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; 
} 
Смежные вопросы