2016-12-21 3 views
1

I Template-Klasse haben, die wie folgt aussieht:C++: Der Zugang Klasse Mitglied von Mitglied ähnlichen Verfahren

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

Natürlich habe ich Elemente dieser Klasse direkt oder durch die Methode zugreifen können, zum Beispiel:

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

Aber wenn ich möchte mehr intuitiven Code machen: statt

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

würde ich gerne Benutzer lassen, tut es durch: v.x = 5.2. Es ist nicht nur eine Laune. Wenn ich eine existierende Bibliothek habe, die einfache Vektorstrukturen eines Formulars wie struct{double x,y,z;} verwendet, könnte ich nach der Methode der Duck-Typisierung meine Template-Klasse erstellen, um in diesem Fall effizient zu sein. Natürlich könnte ich (wahrscheinlich bin ich mir nicht sicher) diese vordefinierte Struktur von referenes - wie: struct{double &x=v.Values[0], &y=v.Values[1], &z=v.Values[2];} - an diese Bibliothek weitergeben, aber ich fürchte, das ist nicht der einfachste Weg, um ein Ziel zu erreichen.

Ah - natürlich könnte ich Referenz-Parameter in meiner Struktur hinzufügen, aber dies würde in der Größe der Elemente zu erhöhen.

+0

warum glauben Sie, dass ein Array mehr effizient, dass diskreter Zugang variabel sein? –

+0

Wenn Sie eine Methode haben, um verschiedene Anzahl von diskreten Variablen zu erstellen, möchte ich es wissen :) – Ch3shire

+1

Vielleicht suchen Sie ein std :: tuple <...> wie Vorlage. Sie können Tupel-Elemente mit dem std :: get < INDEX > abrufen und sie mit std :: tie usw. festlegen? – JimmyNJ

Antwort

4

Hier ist ein Weg, um den gleichen syntaktischen Effekt zu erhalten:

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

den anderen Weg zu gehen ist nicht ganz so angenehm. Es gibt nicht so etwas wie eine Reihe von Referenzen, so eine Abhilfe ist, zu einem Array von std::reference_wrapper greifen:

#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; 
} 
Verwandte Themen