2009-02-21 3 views
2

Je souhaite optimiser mes classes Vector et Matrix (qui sont des modèles de classe pour être exact) en utilisant les instructions SIMD et les intrinsèques du compilateur. Je veux seulement optimiser pour le cas où le type d'élément est "float". L'utilisation des instructions SIMD nécessite de toucher les membres de données. Puisque je ne veux pas être dérangé par la difficulté de maintenir deux classes séparées, je veux pouvoir activer/désactiver certains membres de données basés sur le type du paramètre de modèle. Un autre avantage de cette approche, dans le cas où c'est applicable, est que je peux utiliser le même code du cas général pour les fonctions pour lesquelles je ne veux pas écrire de spécialisation. Par conséquent, ce que je veux réaliser dans le code pseudo est:Inclusion/exclusion conditionnelle des données Membres dans les modèles de classes

template< typename T > 
class Vector3 { 
    if type(T) == float: 
     union { 
      __m128 m128; 
      struct { 
       float x, y, z, pad; 
      }; 
     }; 
    else 
     T x, y, z; 
    endif 
}; 

Je sais que l'inclusion conditionnelle des fonctions des membres est possible grâce à l'utilisation des Boost.enable_if ou des installations similaires. Ce que je cherche cependant, c'est l'inclusion conditionnelle des membres de données. Comme toujours, votre aide est très appréciée. D'autres suggestions valables sont également les bienvenues.

Merci.

+0

Vérifiez cette discussion: http://lists.boost.org/Archives/boost/2009/01 /147103.php – Anonymous

Répondre

3

Une solution qui vient à l'esprit est des modèles partiellement spécialisés, ce que Martin York a publié, mais avec une torsion.

Je recommande un content_type-struct spécial pour fournir le type de mise en page, comme ceci:

// content for non float types 
template<typename T> 
struct content_type { 
    typedef typename T member_type; 
    member_type x,y,z; 
    member_type& X { return x; } 
    // ... 
    // if access to optional members is needed, better use CT_ASSERT or similar 
    member_type& Pad { char assert_error_no_pad_here[0]; } 
}; 

// content for float types 
struct content_type<float> { 
    typedef typename float member_type; 
    member_type x, y, z, pad; 
    member_type& X { return x; } 
    // ... 
    member_type& Pad { return pad; } 
}; 

template<typename T> 
class Vector3 { 
    typedef typename content_type<T> layout_type; 
    typedef typename content_type<T>::member_type member_type; 

    layout_type _content; 

    public: 
    member_type& X { return _content.X(); } 
    memmber_type& Pad { return _content.Pad(); } 
}; 

// or maybe, if memory layout is not important, just inherit (watch for virtual members) 
template<typename T> 
class Vector3 : public content_type<T> { 
    typedef typename content_type<T> layout_type; 
    typedef typename content_type<T>::member_type member_type; 
}; 

L'avantage est que vous suffit d'écrire Vector3 avec toute sa logique une fois.

Vous avez besoin d'un compilateur modérément récent de le faire correctement, bien que (MSVC> 7, gcc> 3)

+0

Excellent. Toute idée de comment je devrais accéder à ces membres de données qui ne font pas partie du dénominateur commun (par exemple "pad"). Une approche consiste à désactiver leurs fonctions membres accesseur correspondantes via Boost.enable_if dans le cas où ces membres de données ne sont pas présents. Merci tabdamage. – Ash

+0

J'ai ajouté une solution pour cela, mais peut-être boost :: enable_if est un peu plus propre. La meilleure solution dépend de votre utilisation réelle, pour que la logique d'exécution soit la plus propre possible, les définitions de type doivent être un peu plus compliquées. – tabdamage