2015-03-08 2 views
1

Je voudrais concevoir une enveloppe en C++ avec une syntaxe simple:Comment concevoir un wrapper de bibliothèque en C++?

Vector<double,stl> v; // aka std::vector<double> 
Vector<double, eigen> w; // aka Eigen::VectorXd from Eigen library 
Matrix<double, eigen> m; // aka Eigen::MatrixXd from Eigen library 

Cependant, je ne parviennent pas à obtenir cette syntaxe, en particulier pour les deux derniers exemples. Voici mon code pour le cas d'emballage des vecteurs STL:

#ifndef WRAPPER_HPP 
#define WRAPPER_HPP 

#include <cstdlib> 
#include <vector> 

//============= 
// BASE WRAPPER 
//============= 

template<class ScalarType, template<class,class...> class WrappedType> 
class Wrapper 
{ 
protected: 
    WrappedType<ScalarType> wrapped_; 
}; 

//============== 
// STL WRAPPER 
//============== 

template<class ScalarType, template<class,class...> class WrappedType> 
struct stl; 

template<class ScalarType> 
struct stl<ScalarType,std::vector> : public Wrapper<ScalarType,std::vector> 
{ 
public: 
    size_t size() 
    { return this->wrapped_.size(); } 
}; 

//======= 
// VECTOR 
//======= 
template<class ScalarType, template<class, template<class,class...> class> class Wrapper> 
using Vector = Wrapper<ScalarType,std::vector>; 
// **** Problem : I should not provide "std::vector" above **** 

#endif 

wrapper STL est une structure appelée stl. Cette structure est en fait une sous-classe de la classe Wrapper. J'ai une structure stl spécialisée pour les vecteurs de STL. Je peux faire d'autres specalisations pour certains conteneurs (listes, cartes, ...). Ainsi, lors de la déclaration

Vector<double,stl> vec 

Je voudrais pouvoir déduire de la paire (Vector, stl) qui correspond à la spécialisation de stl pour std :: vector. Cependant, je n'arrive pas à le faire. Chaque fois que j'essaie quelque chose, j'obtiens une récursion infinie sur les paramètres du template.

Il peut y avoir un bon moyen de le faire avec un typedef ou un alias de template mais je ne le trouve pas. Il peut être quelque chose comme ça:

template<class ScalarType, template<class, template<class,class...> class> class Wrapper> 
using Vector = Wrapper<ScalarType,????>; 

où ???? serait quelque chose d'équivalent à std :: vector, mais déduit de Wrapper. Mais je ne sais pas si c'est possible.

Ma conception peut également être naïve. J'apprécierais vraiment toute suggestion pour l'améliorer. Je ne suis intéressé que par la syntaxe du code.

Merci!

+0

Pourquoi voudriez-vous quelque chose comme ça? Les classes semblent assez sans rapport et arrivent juste à partager des * noms * similaires. –

+0

Pourriez-vous expliquer davantage ce que vous voulez dire? Je voudrais envelopper les bibliothèques externes, mais sans fonctions virtuelles (pour maintenir les performances des bibliothèques enveloppées). – Aleph

+0

Je ne vois pas ce que 'std :: vector ' et 'Eigen :: VectorXd ' ont en commun autre que le nom similaire et la généralisation très large de "contient des éléments". –

Répondre

2

Ceci est assez facile à faire en utilisant la syntaxe C++ 11 ou supérieure.

Voici un exemple de mise en œuvre d'une enveloppe Vector, qui se traduira par la syntaxe que vous cherchez. Utiliser une approche similaire pour mettre en œuvre Matrix, etc.

L'approche combine la spécialisation de modèle, avec template using, en sélectionnant la spécialisation correcte qui déclare un type de membre qui est le type réel d'être déclaré:

#include <vector> 

class stl; // dummy class 
class eigen; // dummy class 

template<typename ...Args> class vector_impl; 

template<> 
class vector_impl<double, stl> { 

public: 
    typedef std::vector<double> impl_type; 
}; 

template<> 
class vector_impl<double, eigen> { 

public: 
    typedef Eigen::VectorXd impl_type; // I presume... 
}; 

// And the magical alias: 

template<typename ...Args> 
using Vector=typename vector_impl<Args...>::impl_type; 

Avec l'être ci-dessus défini:

Vector<double, stl> a; // This declares a std::vector<double> 
Vector<double, eigen> b; // This declares an `Eigen::VectorXd` 

Utilisation de modèles variadique permet pour certains travaux, à savoir quelques modifications supplémentaires peuvent également entraîner des frais supplémentaires, comme le transfert de types allocateur personnalisé à std::vector, etc ...

+0

Merci beaucoup pour votre aide. Non seulement votre solution correspond exactement à mes besoins syntaxiques, mais elle conduit également à un code très simple et clair. – Aleph