2010-09-14 6 views
4

Je suis en train d'accomplirAlternative à la déclaration de modèle de typedef

namespace NTL 
{ 
    typedef std::valarray vector; 
} 

par la norme C++. Je sais que ce n'est pas autorisé, mais j'ai besoin d'un moyen rapide et facile (sans réimplémenter toutes les fonctions, les opérateurs, les surcharges, etc.) pour obtenir un template typedef.

Je suis en train de faire un template de classe Vector qui a un valarray comme membre de données, mais cela me demandera de surcharger toutes les fonctions mathématiques de mon vecteur (encore ... car valarray le fait aussi).

Des idées? Merci! PS: J'aurai probablement besoin d'étendre la fonctionnalité de NTL::vector à un moment donné, et un moyen d'incorporer cela dans la solution serait génial.

Répondre

8

En C++ 0x ce sera très simple, mais pour le moment vous pouvez aborder le problème de deux façons, par une métafonction ou en abusant de l'héritage.

namespace NTL { 
    // metafunction 
    template <typename T> 
    struct vector_1 { 
     typedef std::valarray<T> type; 
    }; 

    // inheritance abuse: 
    template <typename T> 
    struct vector_2 : std::valarray<T> 
    {}; 
} 
int main() { 
    NTL::vector_1<double>::type var1; // type is std::valarray<double> 
    NTL::vector_2<double> var2;  // type inherits from std::valarray<double> 
} 

La seconde approche peut être facilement étendu, mais notez qu'en général il est recommandé de ne pas hériter publiquement des conteneurs STL, car ils ne sont pas conçus pour être étendu. En particulier puisqu'ils n'ont pas de destructeur virtuel, vous pouvez vous retrouver avec un comportement indéfini si votre objet est delete d depuis un pointeur vers le conteneur STL ...

Je vous conseille d'hériter en privé et d'apporter les fonctions de membre de base dans la portée au moyen d'une déclaration using (mieux que de fournir l'héritage public). Il faudra plus de code de plaque de chaudière, mais vous n'aurez pas besoin de fournir des méthodes de transfert pour toutes vos interfaces souhaitées.

BTW, le C++ 0x façon serait:

namespace NTL { 
    template <typename T> 
    using vector = std::valarray<T>; 
} 
+0

Serait-il un moyen sûr C++ 0x d'étendre valarray sans le désordre supplémentaire, en utilisant cette instruction 'using '? Merci – rubenvb

+0

@rubenvb: La drôle de syntaxe C++ est l'équivalent d'un typedef, elle n'est pas conçue pour étendre la classe mais plutôt pour corriger certains arguments de template (pensez que vous voulez avoir des vecteurs de différents types d'éléments avec le même allocateur personnalisé, vous pouvez créer un modèle "typedefed" qui remplira l'allocateur pour vous). –

+0

OK, merci beaucoup. – rubenvb

1

Vous pouvez tirer votre classe de NTL::vectorstd::valarray:

namespace NTL { 
    template <class T> 
    class vector : public std::valarray<T> 
    { 
    public: 
    vector() : std::valarray<T>() { } 
    vector(const std::valarray<T>& other) : std::valarray(other) { } 
    /* other constructors to match the std::valarray constructors */ 

    vector& operator=(const vector&); 
    vector& operator=(const std::valarray<T>&); 
    }; 
} 

De cette façon, un NTL::vector est converti en un std::valarray au début d'une séquence d'opérations, mais le valarray résultant peut également être converti en NTL::vector à nouveau.

Un gros avertissement: Comme stl::valarray n'est pas conçu pour une utilisation polymorphe, vous aurez des problèmes si vous essayez de supprimer un objet NTL::vector via un pointeur std::valarray!

+0

Deux questions: 1. Cela m'oblige à enrouler tous les constructeurs de 'std :: valarray', jusqu'à ce que mon compilateur C++ 0x ait hérité du support du constructeur. 2. Puis-je empêcher qu'un 'NTL :: vector' ne soit converti en' std :: valarray', empêchant ainsi tout 'delete' incorrect? Merci – rubenvb

+0

@rubenvb: 1. Oui, mais la plupart des autres membres ne sont pas nécessaires. Vous pouvez également envisager d'ajouter des constructeurs de mouvements si votre compilateur les prend en charge. 2. Vous pouvez, mais cela vous met au même endroit que vous êtes actuellement avec un membre 'std :: valarray'. –

+0

@Bart: Droit, 2. était une question stupide, je le savais :). Merci pour l'aide. – rubenvb