2016-12-21 4 views
1

J'ai la classe de modèle qui ressemble à ceci:C++: membre de la classe d'accès par la méthode comme membre

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

Bien sûr, je peux accéder à des éléments de cette classe directement ou par la méthode, par exemple:

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

Mais si je voudrais rendre le code plus intuitif: au lieu de

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

Je voudrais permettre à l'utilisateur le faire par: v.x = 5.2. Ce n'est pas seulement un caprice. Si j'ai une bibliothèque existante qui utilise des structures vectorielles simples d'une forme comme struct{double x,y,z;}, je pourrais par la méthode de dactylographie créer ma classe de modèle pour être efficace dans ce cas. Bien sûr, je pourrais (probablement, je ne suis pas sûr) passer à cette bibliothèque prédéfinie structure de referenes - comme: struct{double &x=v.Values[0], &y=v.Values[1], &z=v.Values[2];} mais je crains que ce n'est pas le moyen le plus simple d'obtenir un but. Ah - bien sûr, je pourrais ajouter des paramètres de type référence dans ma structure, mais cela entraînerait une augmentation de la taille des éléments.

+0

pourquoi pensez-vous qu'un tableau sera plus efficace que l'accès variable discrète? –

+0

Si vous avez une méthode pour modéliser un certain nombre de variables discrètes, je veux le savoir :) – Ch3shire

+1

Peut-être que vous cherchez un std :: tuple <...> comme modèle. Vous pouvez récupérer des éléments de tuple en utilisant le std :: get < INDEX > et les définir en utilisant std :: tie et ainsi de suite? – JimmyNJ

Répondre

4

Voici une façon d'obtenir le même effet syntaxique:

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; 
} 

Dans l'autre sens est pas tout à fait si agréable. Il n'y a pas une telle chose comme un tableau de références, donc une solution consiste à recourir à un tableau de 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; 
}