2010-06-08 4 views
10

Je travaille actuellement sur un "moteur" de jeu qui doit déplacer des valeurs entre un moteur 3D, un moteur physique et un langage de script. Comme j'ai besoin d'appliquer très souvent des vecteurs du moteur physique aux objets 3D et que je veux pouvoir contrôler à la fois la 3D et les objets physiques via le système de script, j'ai besoin d'un mécanisme pour convertir un vecteur d'un type (par exemple vector3d<float>) à un vecteur de l'autre type (par exemple btVector3). Malheureusement, je ne peux faire aucune hypothèse sur la façon dont les classes/structures sont disposées, donc un simple reinterpret_cast ne fera probablement pas.Fonctions de conversion non-membres; Diffuser différents types, par ex. Vecteur DirectX au vecteur OpenGL

La question est: Y at-il une sorte de « statique »/procédé de coulée non-membres pour obtenir essentiellement ceci:

vector3d<float> operator vector3d<float>(btVector3 vector) { 
    // convert and return 
} 

btVector3 operator btVector3(vector3d<float> vector) { 
    // convert and return 
} 

En ce moment, ce ne sera pas la compilation car les opérateurs de casting doivent être des méthodes membres . (error C2801: 'operator foo' must be a non-static member)

Répondre

5

Je suggère de les écrire comme une paire de fonctions libres (à savoir ne vous inquiétez pas ce qui les rend « opérateurs »):

vector3d<float> vector3dFromBt(const btVector3& src) { 
    // convert and return 
} 

btVector3 btVectorFrom3d(const vector3d<float>& src) { 
    // convert and return 
} 

void f(void) 
{ 
    vector3d<float> one; 
// ...populate... 
    btVector3 two(btVectorFrom3d(one));  
// ... 
    vector3d<float> three(vector3dFromBt(two)); 
} 
+0

Merci Adam! C'est ce que je fais en ce moment. Je me demande s'il est possible de faire travailler le compilateur. Quelque chose comme "si vous voulez y aller, allez d'abord là-bas". – sunside

+0

Je comprends. Bien que cette solution me semble la plus directe, j'ai ajouté une autre possibilité dans une autre réponse. –

+0

Allez avec des fonctions gratuites. Les conversions implicites sont généralement une mauvaise façon de procéder, même lorsqu'elles sont possibles. – jalf

1

Votre déclaration dans la question est correcte. L'opérateur de conversion de type doit être un membre non statique. Si vous voulez vraiment la sémantique de type de conversion, vous pouvez étendre chacune de ces classes à utiliser dans votre code d'application:

// header: 
class ConvertibleVector3d; 

ConvertibleBtVector : public btVector3 
{ 
    operator ConvertibleVector3d() const; 
} 

ConvertibleVector3d : public vector3d<float> 
{ 
    operator ConvertibleBtVector() const; 
} 

//impl: 
ConvertibleBtVector::operator ConvertibleVector3d() const 
    { 
    ConvertibleVector3d retVal; 
// convert this into retVal... 
    return retVal; 
    } 

ConvertibleVector3d::operator ConvertibleBtVector() const; 
    { 
    ConvertibleBtVector retVal; 
// convert this into retVal... 
    return retVal; 
    } 

void f(void) 
{ 
    ConvertibleVector3d one; 
// ...populate... 
    ConvertibleBtVector two(one);  
// ... 
    ConvertibleVector3d three; 
    three = two; 
} 

Les noms sont un peu bavard mais nous espérons que l'intention est claire. L'héritage public signifie que vous devriez pouvoir utiliser des instances de ces classes de la même manière que la classe de base, sauf qu'elles seront assignables et constructibles les unes des autres. Bien sûr, cela combine les deux classes, mais cela peut être acceptable, car il semble que c'est ce que votre application a l'intention de faire de toute façon.

+0

Merci encore! J'ai accepté l'autre comme réponse.Celui-ci semble plus naturel, mais puisqu'il n'est pas toujours possible de modifier le code de la bibliothèque (bien que dans ce cas-ci) ... et ainsi de suite. :) – sunside

2

Vous pouvez également utiliser une classe wrapper comme basé sur un modèle:

template<class V> 
class vector_cast {}; 

template<> 
class vector_cast<vector3d> { 
    const vector3d& v; 

public: 

    vector_cast(const vector3d& v) : v(v) {}; 

    operator vector3d() const { 
    return vector3d(v); 
    } 

    operator btVector3() const { 
    // convert and return 
    } 
}; 

template<> 
class vector_cast<btVector3> { 
    const btVector3& v; 

public: 

    vector_cast(const btVector3& v) : v(v) {}; 

    operator btVector3() const { 
    return btVector3(v); 
    } 

    operator vector3d() const { 
    // convert and return 
    } 
}; 

Utilisation:

void set_origin(btVector3 v); 

// in your code: 

vector3d v; 
// do some fancy computations 
set_origin(vector_cast(v)); 

// --- OR the other way round --- // 

void set_velocity(vector3d v); 

// in your code: 

btVector3 v; 
// do some other computations 
set_velocity(vector_cast(v));