2011-04-07 4 views
3


Je suis en train de modifier une classe complexe qui a des noeuds pointant sur eux-mêmes comme des listes ou des graphiques liés. Je veux qu'il soit utilisé dans la mémoire partagée à l'aide boost :: fonctions interprocessus. Maintenant, je cherche le moyen de le redessiner de telle sorte qu'il reste générique et implique le moins de changements.Création de classes pour les classes auto-liées avec type de pointeur générique

template< class T > 
class node { 
    public: 
    T data; 
    node* prev; 
    node* next; 
}; 

La refonte devrait utiliser le boost :: :: interprocessus allocateur allocateur afin d'utiliser implicitement les pointeurs intelligents relatifs de type boost :: :: interprocessus offset_ptr. Je pensais que ce devrait impliquer un second paramètre de modèle comme

template< class T, class alloc_type = std::allocator< node<T> > > 
class node { 
    public: 
    T data; 
    typename alloc_type::pointer prev; 
    typename alloc_type::pointer next; 
}; 

qui bien sûr ne fonctionne pas en raison de dépendances cycliques comme des références.
J'espère que peut obtenir de l'aide d'un modèle de classe C++ pro sur la meilleure façon de le mettre en œuvre. J'ai jeté un coup d'œil sur les conteneurs boostés à mémoire partagée, mais ils le résolvent d'une manière plutôt compliquée qui implique plusieurs classes externes.

Joh

+0

Cela ressemble étrangement à une classe de nœuds dans une liste doublement chaînée.Est-ce parce que vous simplifiez le code d'exemple, ou est-ce bien ce à quoi cette classe ressemble? Si ce dernier, pourquoi ne pas utiliser 'std :: list' et passer un custom-allocator? – sbi

+0

C'est en raison de la simplification qu'il s'agit en fait d'une classe arborescente complexe. BTW: avec les implémentations std :: list, cela ne semble pas garantir qu'ils utiliseront le pointeur allocator :: car le standard dit qu'il est équivalent à un pointeur brut. C'est pourquoi boost :: interprocess fournit un ensemble de conteneurs standards. – Joh

Répondre

1

qui bien sûr ne fonctionne pas en raison de dépendances cycliques comme des références.

Oui, cela ne fonctionnera pas, parce que le type node est défini et il est pas encore terminée, mais vous passez à allocator comme paramètre de type. D'où le problème!

En outre, node est un modèle de classe, mais lorsque vous le transmettez à allocator, vous ne fournissez pas d'argument de type pour node. Mais ne vous inquiétez pas, même si vous réussissez, cela ne fonctionnera pas car le type node est pas encore terminée (comme je l'ai déjà dit).


plus que vous avez un autre problème,

alloc_type::pointer prev; 
alloc_type::pointer next; 

Ici, vous devez typename comme

typename alloc_type::pointer prev; 
typename alloc_type::pointer next; 
+1

Et ... 'std :: allocateur < node>' comme 'alloc_type'? –

+0

@Andre: Oui, même c'est un problème. Bon point – Nawaz

+0

Oui, désolé pour les noms de fichiers manquants et le T, je minimisais le code pour montrer le problème de base: c'est une dépendance cyclique des templates de classe. – Joh

0

Il me semble que la classe allocateur appartient au conteneur, et non pas l'élément . Je me rends compte que, pour les conteneurs intrusifs comme le vôtre, ils peuvent être les mêmes. Mais pouvons-nous le factoriser?

Que diriez-vous:

#include <memory> 

template <class T, class alloc_type > 
struct nodePtr { 
    typedef typename alloc_type::pointer pointer; 
    typedef alloc_type allocator; 
}; 


template< class T > 
class node { 
    public: 
    typedef nodePtr<node<T>, std::allocator<node<T> > > pointer; 
    // OR: typedef nodePtr<node<T>, my_allocator<node<T> > > pointer; 
    T data; 
    pointer prev; 
    pointer next; 
}; 

node<int> n; 

Bien sûr, je ne peux pas comprendre comment passer std::allocator<>-node<>, mais peut-être vous ne pas besoin. Avez-vous l'esprit en précisant le nom de votre allocateur au milieu de class node?

Ou peut-être, nous pourrions faire votre allocateur l'allocateur par défaut pour nodePtr?

// untested 
template <class T> class node; 
template <class T, class alloc_type = my_allocator<node<T> > > 
class nodePtr { /* ... */ }; 
template <class T> class node { 
    public: typename nodePtr<T> prev; 
} 
+0

Merci pour votre suggestion, Rob. Le problème est que les nœuds sont enveloppés dans une classe de conteneur qui recevra l'allocateur via le constructeur. C'est comme si c'était fait en boost et nécessaire, si l'allocateur n'est pas apatride. Cependant, je pense que je peux passer un allocateur de vide qui peut être converti en n'importe quel allocateur de type. J'ai donc besoin de construire une structure de données de nœuds liés dans cette classe de conteneur d'une manière générique. – Joh

Questions connexes