web-dev-qa-db-fra.com

Quelle est votre convention pour la typedef'ing shared_ptr?

Je bascule entre les conventions de dénomination pour typer le modèle boost :: shared_ptr. Par exemple:

typedef boost::shared_ptr<Foo> FooPtr;

Avant de conclure une convention, j'aimerais voir ce que les autres utilisent. Quelle est votre convention?

MODIFIER:

Pour ceux qui imbriquent le typedef dans Foo, cela ne vous dérange pas que Foo soit maintenant "conscient" de la façon dont il sera transmis? Cela semble casser l'encapsulation. Que dis-tu de ça:

class Foo
{
public:
    typedef std::vector<Foo> Vector
};

Tu ne ferais pas ça maintenant, n'est-ce pas? :-)

44
Emile Cormier

J'aimerais aussi ajouter quelques options à cette vieille question, même si elles peuvent être très controversées…

Similaire à réponse OldPeculier J'aime les noms de types courts ressemblant le plus possible aux pointeurs standard.

Dans un projet qui utilisait shared_pointer presque partout, j’utilisais

typedef boost::shared_ptr<Foo> Foo_;

// usage examples:
Foo* myFoo0;
Foo_ myFoo1;

J'ai profité de trois choses:

  1. Que le caractère de soulignement ressemble en quelque sorte à un opérateur, mais est surtout traité comme une lettre, de sorte qu'il peut faire partie d'un identifiant (et je vois aucune règle n'interdit à la fin de l'identifiant).
  2. Je n'avais besoin que de trouver one typedef.
  3. Je préfère Foo* myFoo1; à Foo *myFoo1; pour plusieurs raisons, et cela correspond bien à Foo_ myFoo2.

Si vous aviez besoin de typefefs pour différents types de pointeurs intelligents, je choisirais

typedef shared_ptr<Foo> Foo_S;
typedef weak_ptr<Foo>   Foo_W;
typedef unique_ptr<Foo> Foo_U;

// usage examples:
Foo*  myFoo2;
Foo_S myFoo3;
Foo_W myFoo4;
Foo_U myFoo5;

Avec la prise en charge croissante par Unicode des standards et des implémentations de compilateur, je serais tenté d'essayer la syntaxe suivante, en supposant que ces caractères en étoile seraient traités comme une partie régulière de l'identificateur de type. Bien entendu, cela n’est pratique que si tous les développeurs concernés disposent d’une méthode de saisie de texte pratique pour cela:

typedef shared_ptr<Foo> Foo★;
typedef weak_ptr<Foo>   Foo☆;
typedef unique_ptr<Foo> Foo✪;

// usage examples:
Foo* myFoo6;
Foo★ myFoo7;
Foo☆ myFoo8;
Foo✪ myFoo9;

(Un test rapide a montré que cela ne fonctionnait pas, du moins avec mon environnement de construction. Mais il en va de même pour Foo_ä.)

27
Lena Schimmel

Réponse: ne le fais pas. C'est pratique pour vous et pour personne d'autre. Dis ce que tu veux dire.

25
pdusen

Ma préférence:

class Foo
{
public:

    typedef boost::shared_ptr<Foo> SharedPointer;
};

Le seul problème avec FooPtr est que vous pouvez avoir différents types de pointeurs (par exemple, weak_ptrs). Je ne me soucie pas non plus beaucoup des abréviations, mais c’est un tout autre problème.

15
James McNellis

Personnellement, dans le code dont je suis responsable, vous verriez généralement un FofPtr typé dans le même espace de noms que Foo et Foo contiendrait un générique 'SmartPtr' du même type que FooPtr. Avoir FooPtr permet une utilisation manuelle facile et non verbeuse. le fait d'avoir la typedef imbriquée pour 'SmartPtr' ou une valeur équivalente permet une utilisation générique facile dans les modèles, les macros, etc. sans avoir à connaître le type réel du pointeur intelligent.

En outre, je suggérerais d'ajouter une étiquette «subjective» à cette question.

5
Nathan Ernst

J'ai utilisé le typedef externe et encapsulé, mais je me suis retrouvé avec le premier, 

typedef boost::shared_ptr<Foo> FooPtr; 

uniquement parce que, dans les expressions combinées, cela semble plus propre que Foo::Ptr.

Cela ne vous dérange-t-il pas que Foo soit maintenant "conscient" de la façon dont il sera distribué?

Souvent, ces classes ne peuvent être créées que par une méthode fabrique:

struct Foo
{
     static FooPtr Create() { return FooPtr(new Foo); }

   protected:
     Foo() {}
}

C'est un peu plus "fort" que d'encapsuler le typedef, mais c'est un motif très courant.

4
peterchen

J'encapsule généralement le typedef dans la classe. La raison en est que nous avons du code sensible à la mémoire, ce qui facilite le basculement entre boost::shared_ptr et boost::intrusive_ptr Étant donné que intrusive_ptr est quelque chose que la classe doit supporter, il est logique pour moi de savoir quel pointeur partagé utiliser est intégré à la classe.

2
KeithB

Je ne suis pas un grand fan des conventions de nommage hongroises, j'utilise généralement:

typedef boost::shared_ptr<Foo> FooSharedPtr;

Assez détaillé pour être clair mais assez court pour ne pas être un gros problème. Dans tous les cas, j'indiquerais certainement que c'est spécifiquement un pointeur partagé, surtout si vous n'êtes pas le seul à utiliser ce type à l'avenir.

2
Nate

Je ne suis généralement pas fan des identifiants très courts, mais c'est un cas où je les utiliserai.

class Foo
{
public:
    typedef std::shared_ptr<Foo> p;
};

Cela permet à shared_ptr de ressembler autant que possible aux pointeurs ordinaires sans risque de confusion.

Foo* myFoo;
Foo::p myFoo;

Et en ce qui concerne la rupture de l'encapsulation - non, la définition du type shared_ptr au sein de la classe ne rompt pas plus l'encapsulation que la définition de celle-ci en dehors de la classe. Quelle signification de "encapsulation" cela violerait-il? Vous ne dévoilez rien sur la mise en œuvre de Foo. Vous définissez juste un type. Ceci est parfaitement analogue à la relation entre Foo * et Foo. Foo * est un certain type de pointeur sur Foo (le type par défaut, comme cela arrive). Foo :: p est un autre type de pointeur sur Foo. Vous ne rompez pas l'encapsulation, vous ajoutez simplement au système de types.

2
OldPeculier
  typedef shared_ptr<Foo> sptr_Foo;
  typedef weak_ptr<Foo>   wptr_Foo;
  typedef unique_ptr<Foo> uptr_Foo;
1
user846566

Ma première réponse est de demander: "Pourquoi typedef ça?"

En réponse à votre modification: En fait, c'est une approche plutôt intéressante qui pourrait être utile dans de nombreuses situations. En l'utilisant pour revenir à votre question initiale, vous pourriez avoir:


struct object
{
  typedef object* ptr_t;
  typedef shared_ptr<object> shared_ptr_t;
  typedef weak_ptr<object> weak_ptr_t;
  typedef unique_ptr<object> unique_ptr_t;
  etc...
}
1
Crazy Eddie

Je voudrais me débarrasser de l'espace de noms au lieu de raccourcir le type.

using boost::shared_ptr; // or using std::shared_ptr, 
struct Foo
{
    shared_ptr<Foo> impl;
};

Qui a le bonus que vous pouvez facilement changer d’implémentation.

Si c'est encore trop long (je pense que c'est juste):

using boost::shared_ptr;
template<class T> using sptr = shared_ptr<T>;
struct Foo
{
    sptr<Foo> impl;
};
0
alfC

C'est bien quand ça se termine par _t.

class Bar
{
public:
    typedef boost::shared_ptr<Bar> Ptr_t;
};
0
alex vasi

Que diriez-vous:

template <typename T>
class Shared
{
    public: 
        typedef std::shared_ptr<T> Ptr; // or boost::shared_ptr if you will
};

Puis, autorisant toute classe Shared à avoir son propre objet Ptr, comme dans:

class myClass : public Shared<myClass>
{
};

int main()
{
    myClass::Ptr object;
    //...
    object->foo();
}
0
Sergio Basurco

typedef boost::shared_ptr&lt;MyClass> MyClass$;

0
Hideki

C’était l’une des conventions à laquelle j’avais basculé:

typedef boost::shared_ptr<Foo> FooProxy;

... voyant que boost::shared_ptr est une application du motif Proxy .

0
Emile Cormier
class foo;

typedef boost::shared_ptr<foo> foo_p;
typedef boost::weak_ptr<foo> foo_wp;
0
Navrocky