2015-11-24 1 views
0

J'essaie d'écrire une classe de vecteur mathématique. Une première version va comme:Constructeur spécialisé pour la classe Vector

template <typename T, unsigned int n> 
    struct Vector { 
    Vector<T, n>(T t = T()) // default 
    { 
     for (int i = 0; i < n; i++) 
     { 
      data[i] = t; 
     } 
    } 

    Vector<T, n>(const Vector<T, n> &aVector) 
    { 
     for (unsigned int i = 0; i < n; i++) 
     { 
      data[i] = aVector.data[i]; 
     } 
    } 

    Vector<T, n>(const T arr[n]) 
    { 
     for (unsigned int i = 0; i < n; i++) 
     { 
      data[i] = arr[i]; 
     } 
    } 

    T& operator[](unsigned int i); 
    const T& operator[](unsigned int i) const; 
    Vector<T, n>& operator=(const Vector<T, n> &aVector); 

    void normalise(); 

    T data[n]; 
    }; 

J'ai aussi les opérateurs (+, *, etc.) en dehors de la classe déclarai, ainsi que deux autres classes.

Voici la chose cependant. Pour les vecteurs de longueur 2, 3, 4, j'aimerais avoir un constructeur (ou une fonction) qui prend x, y (pour Vec2), x, y, z ou x, y, z, w comme paramètres.

Cependant, il semble que vous ne puissiez pas faire de constructeurs spécialisés à cette fin. Comment dois-je procéder dans ce cas? Dois-je complètement spécialiser trois cas? Cela ne veut-il pas dire que je dois réécrire des morceaux de code? J'ai également une classe Matrix similaire (Matrix), et je suis sûr que je vais avoir besoin de constructeurs pour la rotation, la traduction, la mise à l'échelle, etc. Je suppose que je vais devoir surmonter un problème similaire.

Si vous voyez

J'ai aussi les opérateurs (+, *, etc.) en dehors de la classe déclarai, ainsi que deux autres fonctions (points, croix, etc.).

Voici la chose cependant. Pour les vecteurs de longueur 2, 3, 4, j'aimerais avoir un constructeur (ou une fonction) qui prend x, y (pour Vec2), x, y, z ou x, y, z, w comme paramètres.

Cependant, il semble que vous ne puissiez pas faire de constructeurs spécialisés à cette fin. Comment dois-je procéder dans ce cas? Dois-je complètement spécialiser trois cas? Cela ne veut-il pas dire que je dois réécrire des morceaux de code? J'ai également une classe Matrix similaire (Matrix), et je suis sûr que je vais avoir besoin de constructeurs pour la rotation, la traduction, la mise à l'échelle, etc. Je suppose que je vais devoir surmonter un problème similaire.

Si vous voyez quelque chose dans le code qui vous semble erroné, n'hésitez pas à le signaler en passant.

EDIT: Dans le cas où je n'étais pas assez clair, les tableaux sont censés être unidimensionnels, et tous ses composants sont du même type. Les spécialisations sont pour les tableaux avec 2, 3 et 4 éléments.

+0

Sur une note de côté - votre classe 'vECTOR' n'a pas besoin constructeur de copie défini par l'utilisateur ou opérateur d'affectation. – PaulMcKenzie

+0

Pourquoi pas? – spliblib

+0

'Pour les vecteurs de longueur 2, 3, 4' Voulez-vous dire le nombre de * dimensions * peut être 2, 3 ou 4? – PaulMcKenzie

Répondre

0

Vous pouvez utiliser un modèle variadique:

#include <chrono> 
#include <future> 
#include <iostream> 
#include <stdexcept> 


template<typename T, unsigned int n> 
struct Vector 
{ 
    // Note: We need x and y: 
    // The default (in the question) is a constructor taking a single argument. 
    template <typename ... Args> 
    Vector(T x, T y, Args ... args) 
    { 
     static_assert(sizeof ... (Args) == n - 2, "Invalid number of arguments"); 
     auto initializer_list = { x, y, std::forward<Args>(args)... }; 
     std::copy(initializer_list.begin(), initializer_list.end(), data); 

    } 

    T data[n]; 
}; 


template<typename T, unsigned int n> 
void print(const Vector<T, n>& v) { 
    for(unsigned i = 0; i < n; ++i) 
     std::cout << v.data[i] << ' '; 
    std::cout << '\n'; 
} 


int main() 
{ 
    Vector<int, 2> v2(1, 2); 
    Vector<int, 3> v3(1, 2, 3); 
    Vector<int, 4> v4(1, 2, 3, 4); 
    print(v2); 
    print(v3); 
    print(v4); 

    // Invalid number of arguments 
    // Vector<int, 3> e2(1, 2); 

    // Invalid number of arguments 
    // Vector<int, 3> e4(1, 2, 3, 4); 
    return 0; 
} 
0

Personnellement, je voudrais déclarer différentes classes pour chaque vecteur. Vec2<T1, T2>, Vec3<T1, T2, T3> et Vec4<T1, T2, T3, T4>. Rendre chaque classe Vec* hériter publiquement une classe de base sans modèle Vector, puis créer une fonction statique create dans Vector avec une surcharge pour chaque type Vec* qui sera chargé de les créer. Pseudo-exemple pour Vec3:

template<T1, T2, T3> static std::shared_ptr<Vector> create(T1 a1, T2 a2, T3 a3) 
{ 
    return new Vec3<T1, T2, T3>(a1, a2, a3); 
} 
auto vec = Vector::create<int, int, int>(1, 2, 3); 
0

modèle variadique et SFINAE peut résoudre cela. mais je pense que le plus simple serait d'hériter de (spécialisés) aide

template <typename T, unsigned int n> 
struct VectorHelper<T, n> 
{ 
    T data[n]; 
}; 

template <typename T> 
struct VectorHelper<T, 2> 
{ 
    VectorHelper(T x, T y) : {data[0] = x; data[1] = y;} 
    T data[2]; 
}; 

template <typename T> 
struct VectorHelper<T, 3> 
{ 
    VectorHelper(T x, T y, T z) : {data[0] = x; data[1] = y; data[2] = z} 
    T data[3]; 
}; 


template <typename T, unsigned int n> 
struct Vector : private VectorHelper<T, n> 
{ 
    using VectorHelper<T, n>::VectorHelper; // use base constructor(s) 
    // your previous implementation without `data` (as member of base) 
};