2017-03-07 12 views
1

J'essaie d'implémenter un vecteur (dans le sens mathématique) en utilisant des modèles. Je voudrais définir les constantes vectorielles standard dans la classe. J'ai réussi à le faire pour des constantes simples (tous les zéros, tous les uns) mais je me bats maintenant pour définir les vecteurs unitaires les plus difficiles (tous les zéros sauf un composant mis à un à un index donné).Modèle C++ statique membre const variable dans la classe modèle

Je n'ai pas encore trouvé une façon élégante de le faire. Voici comment je voudrais définir que:

#include <iostream> 

template<unsigned int tSize, typename tReal> 
class Vector { 
public: 

    template<unsigned int tIndex> 
    static const Vector msUnit; 

    inline Vector() {} 

    template<typename...tTypes> 
    inline Vector (tTypes...pVals) { 
     set(mReals, pVals...); 
    } 

    inline tReal operator[] (unsigned int pIndex) { 
     return mReals[pIndex]; 
    } 

    inline const tReal operator[] (unsigned int pIndex) const { 
     return mReals[pIndex]; 
    } 

protected: 

    template<typename tType> 
    void set (tReal* pPtr, const tType pVal) { 
     *pPtr = pVal; 
    } 

    template<typename tType, typename...tTypes> 
    void set (tReal* pPtr, const tType pVal, const tTypes...pVals) { 
     *pPtr = pVal; 
     set(pPtr+1, pVals...); 
    } 

    tReal mReals [tSize]; 

}; 

int main() { 

    Vector<3,double> lVec = Vector<3,double>::msUnit<2>; 

    std::cout << "Vector: (" << lVec[0] << ", " << lVec[1] << ", " << lVec[2] << ")" << std::endl; 

    return 0; 
} 

Mais je ne l'ai pas trouvé un moyen de définir le modèle de membre const statique msUnit.

J'ai essayé ceci:

template<unsigned int tIndex, unsigned int tSize, typename tReal> 
    const Vector<tSize,tReal> Vector<tSize,tReal>::msUnit<tIndex>; 

Mais compilateurs (clang & gcc) de porter plainte:

prog.cc:43:48: error: nested name specifier 'Vector<tSize, tReal>::' for declaration does not refer into a class, class template or class template partial specialization 
const Vector<tSize,tReal> Vector<tSize,tReal>::msUnit<tIndex>; 
          ~~~~~~~~~~~~~~~~~~~~~^ 
prog.cc:43:54: error: expected ';' at end of declaration 
const Vector<tSize,tReal> Vector<tSize,tReal>::msUnit<tIndex>; 
                ^
                ; 
prog.cc:43:54: error: expected unqualified-id 

Voici un exemple vivant de ce test: http://melpon.org/wandbox/permlink/AzbuATU1lbjXkksX

Est-il même possible de avoir des membres de variable de modèle const statiques dans les classes de modèle? Et si oui, comment?

Et je dois encore trouver un moyen de fournir un initialiseur pour le modèle msUnit.

+1

Je n'ai pas d'expérience avec des modèles variables (donc ceci est un commentaire et non une réponse), mais je vous attendez la syntaxe à 'template modèle const Vecteur Vecteur :: msUnit ; ' – Angew

+0

Comme pour l'initialiseur, cela impliquera probablement une récursivité. – Angew

+1

Votre définition proposée ne définit vraiment rien. Pour réellement définir un modèle, vous devez fournir les paramètres du modèle réel, c'est-à-dire ce qui est 'tIndex',' tSize', et 'tReal'. –

Répondre

3

Vous avez déjà trouvé la manière dont vous pouvez decleare votre msUnit - vous devez utiliser deux modèles, à savoir

template<unsigned tSize, typename tReal> 
template<unsigned tIndex> 
const Vector<tSize, tReal> Vector<tSize, tReal>::msUnit; 

Comme vous avez actuellement aucun constructeur correspondant pour initialiser l'argument n-ième à un et tous les autres à zéro (ce qui n'aurait pas de sens je suppose), vous pouvez simplement utiliser votre propre fonction. Comme vous accédez déjà membre statique de votre classe, vous avez également accès à votre classe complète, vous pouvez simplement utiliser

template<unsigned int tSize, typename tReal> 
class Vector { 
public: 
    // ... 

    template<unsigned int tIndex> 
    static const Vector msUnit; 

private: 
    static const Vector<tSize, tReal> createUnitVector(unsigned tIndex) { 
     Vector<tSize, tReal> v{}; 
     v.mReals[tIndex] = tReal(1); 
     return v; 
    } 

    tReal mReals [tSize]; 
}; 

template<unsigned tSize, typename tReal> 
template<unsigned tIndex> 
const Vector<tSize, tReal> Vector<tSize, tReal>::msUnit{Vector::createUnitVector(tIndex)}; 

Donc, tout comme vous l'avez déjà, mais vous initialisez votre vecteur avec une autre fonction donnée Dans votre classe.

Ici, vous allez pour la démonstration en direct: http://melpon.org/wandbox/permlink/5b7cgXTeqXZDoCRp

+0

Salut, j'ai accepté la réponse, mais j'ai choisi de passer à un modèle de méthode statique, donc je n'ai pas besoin de tirer les extensions C++ 14 (pour les variables de template). – Lagf