2017-10-10 16 views
0

de travail sur une classe d'arbre avec une interface STL-like, j'ai rencontré un problème en utilisant non des éléments par défaut constructible:élément sortant la dernière pour les éléments non par défaut constructible

Comme je suis la mise en œuvre itérateurs, je besoin d'un élément passé-dernier à tout moment. Mon approche est d'en créer un dans le constructeur, qui affirme que le type de valeur est constructible par défaut.

Existe-t-il une approche pour se débarrasser de cette contrainte?

+1

Le placement nouveau peut vous épargner la construction prématurée ... juste dire – StoryTeller

+9

Passé les éléments d'extrémité ne sont pas censés exister. – nwp

+1

Quand vous dites passé-le-dernier élément, vous voulez peut-être dire un élément 'end', qui pour les tableaux bruts peut être un pointeur vers un passé le dernier élément, mais n'est pas obligé d'être. Vous pouvez faire un type de sentinelle pour représenter 'end' à la place. – AndyG

Répondre

2

La fin de la fin ne peut pas être nullptr si votre itérateur est bidirectionnel, end()-- doit être légale.

Il peut être implémenté à la place par une sentinelle, et dans ce cas, la sentinelle ne devrait même pas contenir un élément construit par défaut.

Cela peut être fait en tant que telle

struct link 
{ 
    link *parent, *left, *right; 
}; 

template<typename T> 
struct node : link 
{ 
    T data; 
}; 

template<typename T> 
struct tree : link 
{ 
    // tree itself serves as the sentinel 
    // At initialization parent and childs should all point to the sentinel 
    tree() : parent(this), left(this), right(this) {} 

    // ... 
}; 

Et itérateurs ont pas besoin d'un traitement spécial pour le cas passé final.

// nested within tree 
struct iterator 
{ 
    explicit iterator(link* l) : n(l) {} 
    iterator& operator--() { n = n->parent; return *this; } // or something else 
    auto& operator*() { return reinterpret_cast<node<T>*>(n)->data; } 

    // ... 

    link* n; 
}; 
iterator begin() { return {left}; } // or something else 
iterator end() { return {this}; } 
+0

Vous pouvez totalement avoir le type itérateur être 'nullptr'. Vous avez juste besoin d'ajouter une vérification dans 'operator -()'. On peut dire que cela vaut mieux que de laisser tomber le type de nœud dans le code client. – nwp

+1

@nwp Le type de noeud n'est pas divulgué, vérifiez l'interface de 'tree'. Comment allez-vous en arrière d'un 'nullptr'? Dites quand vous avez 2 arbres, comment savez-vous à quel 'end()' vous faites référence? Notez que l'itérateur n'a qu'un seul pointeur, il n'y en a pas un autre pointant vers l'arbre lui-même –

+0

Voilà la solution générale que je cherchais, @PasserBy! – SimdSeemsSuitable

0

I a résolu le problème en stockant un autre pointeur vers le noeud racine, à partir de laquelle je peux recréer le dernier élément de constante de temps.