Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's your convention for typedef'ing shared_ptr?

I'd like too add some options to this old question, even though they might be highly controversial…

Similar to OldPeculier's answer I like short type names that resemble standard pointers as closely as possible.

In a project that used shared_pointer almost everywhere, I used

typedef boost::shared_ptr<Foo> Foo_;

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

I took advantage of three things:

  1. That the underscore character somehow looks like an operator, yet is treated mostly like a letter, so that it can be part of an identifier (and I see no rule forbidding it at the end of the identifier).
  2. That I only needed to come up with one typedef.
  3. I prefer Foo* myFoo1; over Foo *myFoo1; for several reasons, and it matches nicely with Foo_ myFoo2.

When in need of typedefs for different kinds of smart pointers, I'd go for

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;

With increasing Unicode support in the standards and compiler implementations, I'd be tempted to try the following syntax, assuming that those star characters would be treated as a regular part of the type identifier. Of course this is only practical if all involved developers have a convenient text input method for this:

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;

(A quick test indicated that this does not actually work, at least with my build environment. But the same is true for Foo_ä.)


Answer: don't do it. It's convenient for you and nobody else. Say what you mean.


My preference:

class Foo
{
public:

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

The problem with just FooPtr is that you may have different types of pointers (e.g., weak_ptrs). I also don't much care for abbreviations, but that's another matter altogether.


Personally, in the code I'm responsible for, you'd typically see a FooPtr typedef'd at the same namespace scope as Foo and Foo would contain a generically named 'SmartPtr' typedef to the same type as FooPtr. Having FooPtr allows for easy an non-verbose manual usage. having the nested typedef for 'SmartPtr' or some quivalent allows for easy generic usage in templates, macros, etc. without having to know that actual type of the smart pointer.

Also, I'd suggest adding a 'subjective' tag to this question.


I have used both the outer and encapsulated typedef, but ended up with the first,

typedef boost::shared_ptr<Foo> FooPtr; 

solely because in combined expressions this looks cleaner than Foo::Ptr.

Doesn't it bother you that Foo is now "aware" of how it will be passed around?

Often enough, these classes are creatable through a factory method only:

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

   protected:
     Foo() {}
}

That's kind of "stronger" than encapsulating the typedef, yet a very common pattern.