I\'m flip-flopping between naming conventions for typedef\'ing the boost::shared_ptr template. For example:
typedef boost::shared_ptr FooPtr;
I'm not a big fan of Hungarian naming conventions, I usually use:
typedef boost::shared_ptr<Foo> FooSharedPtr;
Detailed enough to be clear but short enough to not be a huge hassle. In any case, I would definitely indicate it's specifically a shared pointer, especially if you're not the only one who's going to be using that type in the future.
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:
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_ä
.)
My first response is to ask, "Why typedef that?"
In reply to your edit: Actually that's a rather interesting approach that could be useful in many situations. Using it to go back to your original question you might have:
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...
}
I'm generally not a fan of very short identifiers, but this is one case where I'll use them.
class Foo
{
public:
typedef std::shared_ptr<Foo> p;
};
This enables shared_ptr to resemble ordinary pointers as closely as possible without risk of confusion.
Foo* myFoo;
Foo::p myFoo;
And as for breaking encapsulation—no, typedefing the shared_ptr type within the class doesn't break encapsulation any more than typedefing it outside of the class. What meaning of "encapsulation" would it violate? You're not revealing anything about the implementation of Foo. You're just defining a type. This is perfectly analogous to the relationship between Foo* and Foo. Foo* is a certain kind of pointer to Foo (the default kind, as it happens). Foo::p is another kind of pointer to Foo. You're not breaking encapsulation, you're just adding to the type system.
Answer: don't do it. It's convenient for you and nobody else. Say what you mean.
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.