2009-01-31 7 views

Répondre

1

« Comment puis-je déclarer et définir dans cette classe »

dans quelle classe? Vous avez défini un modèle de classe, pas une classe. Vous ne pouvez pas appeler une fonction statique d'un modèle de classe lui-même, vous devez appeler une version particulière de la fonction statique qui fait partie d'une classe réelle.

Alors, voulez-vous le modèle (et donc tous les instanciations de celui-ci) d'avoir une fonction renvoyant un StaticVector , ou vous voulez un instanciation particulier de ce modèle pour avoir une fonction renvoyant un StaticVector ?

Si l'ancien:


    template <unsigned int N> 
    struct SV { 
    int contents[N]; 
    static SV<3> get3dVec(int x, int y, int z) { 
     SV<3> v; 
     v.contents[0] = x; 
     v.contents[1] = y; 
     v.contents[2] = z; 
     return v; 
    } 
    }; 

    int main() { 
    SV<3> v = SV<1>::get3dVec(1,2,3); 
    } 

fonctionne pour moi.

Dans ce dernier cas (vous ne souhaitez que get3dVec être membre de SV , pas de tous les SV <tout>), alors vous voulez la spécialisation du modèle:


    template <unsigned int N> 
    struct SV { 
    int contents[N]; 
    }; 

    template<> 
    struct SV<3> { 
    int contents[3]; // must be re-declared in the specialization 
    static SV<3> get3dVec(int x, int y, int z) { 
     SV<3> v; 
     v.contents[0] = x; 
     v.contents[1] = y; 
     v.contents[2] = z; 
     return v; 
    } 
    }; 

    int main() { 
    SV<3> v = SV<1>::get3dVec(1,2,3); // compile error 
    SV<3> v = SV<3>::get3dVec(1,2,3); // OK 
    } 

Si pour aucune autre raison que pour rendre le code appelant plus beau en omettant le paramètre de template fondamentalement non pertinent, je suis d'accord avec Iraimbilanja que normalement une fonction libre (dans un espace de noms si vous écrivez pour la réutilisation) aurait plus de sens pour cet exemple. Les modèles C++ signifient que vous n'avez pas besoin de fonctions statiques autant en C++ qu'en Java: si vous voulez une fonction "foo" qui fait une chose pour la classe Bar et une autre chose pour la classe Baz, vous pouvez déclarer comme un modèle de fonction avec un paramètre de modèle qui peut être Bar ou Baz (et qui peut ou non être déduit des paramètres de la fonction), plutôt que d'en faire une fonction statique sur chaque classe. Mais si vous voulez que ce soit une fonction statique, alors vous devez l'appeler en utilisant une classe spécifique, pas seulement un nom de modèle.

0

Quelque chose comme:

template< unsigned int SIZE > 
StaticVector<SIZE> createVec(const std::tr1::array< double, SIZE >& values) 
{ 
    StaticVector<SIZE> vector; 
    for(int i = 0; i < values.size(); ++i) // here assuming that StaticVector have [] operator to access values on write 
    { 
     vector[i] = values[i]; 
    } 

    return vector; 
} 

... ou une variante serait certainement travailler. (Did'nt tester)

utilisation serait:

std::tr1::array< double, 3 > vectorValues = { 10.0, 10.0, 42.0 }; 

StaticVector<3> vector1 = createVector(vectorValues); // if the compiler can guess the size from the array information 
StaticVector<3> vector2 = createVector<3>(vectorValues); // if you have to specify the size 

Une alternative serait de remplacer std :: tr1 :: tableau par un ensemble de base, mais il utiliserait des tableaux bruts à vos propres risques :)

0

D'abord, je crois que vous voulez dire à l'origine pour retourner

StaticVector<N> 

Au lieu de toujours une spécialisation avec N == 3.Donc, ce que vous voulez faire est écrit comme ceci:

template <unsigned int N> 
class StaticVector { 
public: 
    // because of the injected class-name, we can refer to us using 
    // StaticVector . That is, we don't need to name all template 
    // parameters like StaticVector<N>. 
    static StaticVector create3dVec(double x1, double x2, double x2) { 
     // create a new, empty, StaticVector 
     return StaticVector(); 
    } 

}; 

Si vous voulez vraiment revenir toujours un 3dVector, vous voudrez probablement limiter à N == 3, de sorte que, par exemple StaticVector<4>::create3dVec n » t travail. Vous pouvez le faire en utilisant la technique décrite here.

Si vous voulez avoir une fonction comme createVec qui fonctionne avec n'importe quelle taille, vous voudrez probablement remplacer les paramètres par un tableau. Vous pouvez faire autrement, mais cela est avancé et nécessite quelques astuces de macro appliquées avec boost :: preprocessor. Ça ne vaut pas le coup je pense. La prochaine version C++ fournira modèles variés à cette fin. Quoi qu'il en soit, pensez à utiliser quelque chose comme ceci:

Je pense que cela ne ferait que compliquer inutilement ici. Une solution rapide est d'utiliser un boost :: fusion :: vecteur lieu, le mettre dans le modèle de classe au lieu de la version ci-dessus:

static StaticVector createVec(double (&values)[N]) { 
    // create a new, empty, StaticVector, initializing it 
    // with the given array of N values. 
    return StaticVector(); 
} 

Vous pouvez l'utiliser avec

double values[3] = {1, 2, 3}; 
StaticVector<3> v = StaticVector<3>::createVec(values); 

Notez qu'il accepte un tableau par référence. Vous ne pouvez pas lui donner un pointeur. C'est parce qu'il correspond à l'utilisation des paramètres: Vous ne pouvez pas fournir moins ou plus d'arguments pour l'autre sens. Il vous protégera également des cas comme ceci:

// oops, values is a null pointer! 
StaticVector<3> v = StaticVector<3>::createVec(values); 

Un tableau ne peut jamais être un pointeur nul. Bien sûr, si vous le souhaitez, vous pouvez toujours changer le paramètre de tableau en pointeur. Il serait tout simplement ma préférence personnelle :)

0

@litb

Je voulais retourner un vecteur 3-élément. La raison en est que ces vecteurs sont censés être des entités géométriques, il n'est donc pas nécessaire que N soit trop élevé (je ne suis pas un physicien de cordes, donc je ne travaille pas dans des espaces à 11 dimensions). Je voulais créer un modèle pour éviter la duplication du code mais garder les vecteurs à 1, 2 et 3 dimensions en tant que types séparés.

+0

Si certaines dimensions sont des cas spéciaux, vous pourriez trouver utile de faire "typedef StaticVector <3> Vec3;" ou "class Vec3: public StaticVector <3> {". Le premier vous rappelle juste que c'est spécial. Ce dernier vous permet de définir les propriétés "spéciales" de Vec3 mais de laisser StaticVector <3> seul au cas où. –

+0

... juste au cas où vous voulez réellement un StaticVector <3> qui n'a pas le comportement spécial, je veux dire. –

Questions connexes