Is it always evil to have a struct with methods? - c++

I've just been browsing and spotted the following...
When should you use a class vs a struct in C++?
The consensus there is that, by convention, you should only use struct for POD, no methods, etc.
I've always felt that some types were naturally structs rather than classes, yet could still have a few helper functions as members. The struct should still be POD by most of the usual rules - in particular it must be safe to copy using memcpy. It must have all member data public. But it still makes sense to me to have helper functions as members. I wouldn't even necessarily object to a private method, though I don't recall ever doing this myself. And although it breaks the normal POD rules, I wouldn't object to a struct having constructors, provided they were just initialise-a-few-fields constructors (overriding assignment or destructors would definitely be against the rules).
To me a struct is intuitively a collection of fields - a data structure node or whatever - whereas a class is an abstraction. The logical place to put the helper functions for your collection-of-fields may well be within the struct.
I even think I once read some advice along these lines, though I don't remember where.
Is this against accepted best practice?
EDIT - POD (Plain Old Data) is misrepresented by this question. In particular, a struct can be non-POD purely because a member is non-POD - e.g. an aggregate with a member of type std::string. That aggregate must not be copied with memcpy. In case of confusion, see here.

For what it's worth, all the standard STL functors are defined as structs, and their sole purpose is to have member functions; STL functors aren't supposed to have state.
EDIT: Personally, I use struct whenever a class has all public members. It matters little, so long as one is consistent.

As far as the language is concerned, it doesn't matter, except for default private vs. public access. The choice is subjective.
I'd personally say use struct for PODs, but remember that "POD" doesn't mean "no member functions". It means no virtual functions, constructors, destructor, or operator=.
Edit: I also use structs for simple public-access aggregates of data, even if their members aren't PODs.

I tend to use struct a lot.
For the "traditional" OOP classes (the ones that represent a specific "thing"), I tend to use class simply because it's a common convention.
But most of my classes aren't really OOP objects. They tend to be functors, and traits classes and all sorts of other more abstract code concepts, things I use to express myself, rather than modelling specific "things". And those I usually make struct. It saves me having to type the initial public:, and so it makes the class definition shorter and easier to get an overview of.
I also lean towards making larger, more complex classes class. Except this rarely affects anything, because I lean even more towards refactoring large, complex classes... And then I'm left with small simple ones, which might be made struct's.
But in either case, I'd never consider it "evil". "Evil" is when you do something that actively obfuscates your code, or when you make something far more complex than necessary.
But every C++ programmer knows that struct and class mean virtually the same thing. You're not going to be confused for long because you see a struct Animal {...}; You know that it's a class designed to model an animal. So no, it's not "evil" no matter which way you do it.

When I have control over the style guides, everything is defined as a struct. Historically, I wanted all my objects to be one or the other, since I was taught it was undefined behavior to forward declared a struct as a class, and vice versa (I'm not sure if this was ever actually true, its just what I was told). And really, struct has the more reasonable default state.
I still do the same because I've never been convinced of the value of using it as a form of documentation. If you need to convey that an object only has public members, or doesn't have any member functions, or whatever arbitrary line you chose to draw between the two, you have actual documentation available for that. Since you never actually use the struct or class keyword when using the type, you would need to go hunting for the definition anyhow if you want the information. And with everybody having their own opinion on what struct actually means, its usefulness as self-documentation is reduced. So I shoot for consistency: everything as one or the other. In this case, struct.
Its not a popular way of doing things, to say the least. Fortunately for everybody involved, I very rarely have control over the coding standards.

I use a struct whenever I need an aggregate of public data members (as opposed to class, which I use for types that come with a certain level of abstractions and have their data private).
Whether or not such a data aggregate has member functions doesn't matter to me. In fact, I rarely ever write a struct without also providing at least one constructor for it.

You said, "To me a struct is intuitively a collection of fields - a data structure node or whatever". What you are describing is Plain Old Data. The C++ standard does have an opinion of what POD means with respect to C++ language features. I suggest that, where possible, you adopt the meaning of POD used in C++0x.
I need to find a reference for this, but I thought that, as far as type definitions are concerned, the keywords "struct" and "class" are to be synonyms in C++0x. The only difference being that class defaults to private members, while a struct defaults to public. This means that you'll never see complier error messages like "Type X first seen using struct, now seen using class." once we're all using C++0x.
I think that it is wrong to have strict rules on when to use class and when to use struct. If consistency is important to you, the go ahead and make a coding standard that has what ever sort of rules you like. Just make sure everyone knows that your coding standard relates to how you want you code to look - it doesn't relate to the underlying language features at all.
Maybe to give an example where I break all your rules, you say "To me a struct is intuitively a collection of fields - a data structure node or whatever - whereas a class is an abstraction." When I want to write a class that implements some abstraction, I define the interface as a struct with pure virtual methods (egad!) - this is exposed in a header, as too is a factory method to construct my concrete class. The concrete class is not exposed i a public header at all. Since the concrete class is a secret, it can be implemented however I like and it makes no difference to external code.
I'd suggest that if you think that the keywords struct and class have any relation to the concept of POD, then you're not understanding C++ yet.

Related

C++ Structs - Pointless? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What are the differences between struct and class in C++
I'm just trying to figure out if using 'C structs' in C++ are essentially useless or not. Do you gain anything by using them (opposed to simply creating another class)?
In C the point of structs is obvious, simply contiguous allocations of grouped data and a nice way to access said data, in C++ I feel the role becomes a little more vague.
Seeing as that you can have functions which are members of structs, instance variables, and visibility labels, the only real difference that I see between structs and classes in C++ is that struct members default to public while class members default to private. The way I see them, they can actually both be implemented with the same exact underlying system.
So am I missing something here as to the purpose of structs in C++? Or have they kind of lost their purpose, as I feel they have in C++?
In my opinion, Structures doesn't give you anything that can't be implemented by a class.
But, Structures are kept in C++ in order to have backward compatibility with c
Classes and structures in C++ are almost the same, the only things that separates them is that the default visibility of a class is private while in a struct it's public.
The reason to keep having structures in C++ was probably to keep the language compatible with C, so it would be easier to port C code to C++, or for programmers to make that transition.
As for the usage of structures contra classes, I personally use them just like would in C, to group related variables together in a single "object".
Undoubtedly the reason they are there is for compatibility with C. But you are right, although there are small differences between class and struct in C++ there is nothing you can do with structs that you cannot do with classes (and vice versa).
Personally I use structs only when the same declaration would be legal in C, to emphasize the C-like nature of whatever it is I'm doing.
They are implemented "with the same exact underlying system". In fact, you can actually declare a type using class keyword and then define it using struct keyword. Basically, they are exactly the same aside from the conceptual difference you already mentioned: default access rights.
I don't see though why would one call them "useless". The usage of the keyword became a matter of personal preference and/or coding standard. Like "use struct fro POD types", or "use struct for types with no incapsulation/access control".
With the same degree of success one can declare the built-in -> operator "useless" because of its equivalence to *+. combination.
You can have the same behavior as in C, nobody forces you to use the additional "class" features. So if you understand their purpose in C, it should be understandable in C++ as well (the "C-like" portion at least).
As Joachim Pileborg already pointed out, classes and structures are almost the same thing in C++.
I would, however, recommend to use struct for "dumb" data holders with public members and class for properly encapsulated classes as a style convention.

In C++, why struct is in fact class?

The other topic and responses there made me ask this question:
Why does C++ allow struct to behave just like class? At one hand, C++ made it compatible with C-struct by making it's members public by default (just like in C), while on the other hand, it made it look-like class by allowing it to be inherited from classes, and applying other object-oriented techniques (not so much like C-struct anymore). Why did it not make it just plain old C-struct with no OOP? Any special reason?
It allows existing structs to be fitted in with C++ code in a more natural way. For instance, you can add member functions to a struct and inherit from a struct, which wouldn't be possible if structs and classes inhabited different universes.
Stroustrup's original intent was to avoid a fracturing of the community between the traditional C-style "struct" camp, and the OO "class" crowd. He also cited the benefits of having just one concept instead of two.
From a language point of view, structures and unions are just types of class. It makes the language specification simpler if there are fewer concepts (with a small letter 'c') and it also makes specifying the language less error prone as it is less easy to miss something 'obvious' out if every common property had to spelled out for each of structures, unions and non-structure, non-union classes.
C++ classes have a lot of potential functionality over C structures but as C structures can be viewed as a degenerate C++ class, it is simplest to allow them to be exactly this. There is no benefit to having a special structure concept as well as a class concept.
From ISO/IEC 14882:2003, 9 [class] / 4:
A structure is a class defined with the class-key struct; its members and base classes are public by default. A union is a class defined with the class-key union; its members are public by default and it holds only one data member at a time.
"public" default for struct fields is required for compatibility with C
code which may access struct fields.
"public" default for struct inheritance is required so that the child class
could be used in place of base struct.
It could be possible to make struct into a different data type than classes
(ie disallow access type specifiers and methods in it), but that would be both
inconvenient for programming and add a lot of unnecessary work for compiler
developers.
In C there were only structs to begin with. Object orientation began when libraries were designed when pointers to those structures were passed to a set of library functions that were dependent on that structure. One good example is the Win32 API. It isn't a C++ interface, it's a C interface; but it's still object oriented.
Classes are almost the same as structures memory-wise. The member functions are not stored as part of the class member data. It's simply a structure with extra function pointers on the end. So a class' function table is dereferenced in the same way that Windows API uses object orientation, but it encapsulates it so you don't see it.
Inheritance, polymorphism; who cares? People were fine with C, and still doing fine with C.
Allowing something you declare as struct to really be a class allows type-safety when creating a C interface.
You can forwardly declare your struct for your C interface:
struct Foo;
You can declare methods on it
void doStuffThatModifiesFoo( struct Foo * foo, ... );
struct Bar getStuffFromFoo( const struct Foo * foo );
You can also write create and destroy methods for it.
Underneath you implement Foo not as a C struct but as a class but your C clients do not need to know that. This is better than passing it around as a void * then casting (not safe if someone passes you a void* to a completely different type and you cast it).
The "compatibility with C" issue is only meant in one direction: Old, valid C-code should also compile as C++ code. The other way round is impossible as soon as any language feature that only C++ has is being used.
That means in C++, you always write classes, you can omit using the keyword struct at all ; though some, including me, think they come in handy to show that a class just a simple collection of named values, with no real encapsulation or possibly complex behaviour.

Unions as Base Class

The standard defines that Unions cannot be used as Base class, but is there any specific reasoning for this? As far as I understand Unions can have constructors, destructors, also member variables, and methods to operate on those varibales. In short a Union can encapsulate a datatype and state which might be accessed through member functions. Thus it in most common terms qualifies for being a class and if it can act as a class then why is it restricted from acting as a base class?
Edit: Though the answers try to explain the reasoning I still do not understand how Union as a Derived class is worst than when Union as just a class. So in hope of getting more concrete answer and reasoning I will push this one for a bounty. No offence to the already posted answers, Thanks for those!
Tony Park gave an answer which is pretty close to the truth. The C++ committee basically didn't think it was worth the effort to make unions a strong part of C++, similarly to the treatment of arrays as legacy stuff we had to inherit from C but didn't really want.
Unions have problems: if we allow non-POD types in unions, how do they get constructed? It can certainly be done, but not necessarily safely, and any consideration would require committee resources. And the final result would be less than satisfactory, because what is really required in a sane language is discriminated unions, and bare C unions could never be elevated to discriminated unions in way compatible with C (that I can imagine, anyhow).
To elaborate on the technical issues: since you can wrap a POD-component only union in a struct without losing anything, there's no advantage allowing unions as bases. With POD-only union components, there's no problem with explicit constructors simply assigning one of the components, nor with using a bitblit (memcpy) for compiler generated copy constructor (or assignment).
Such unions, however, aren't useful enough to bother with except to retain them so existing C code can be considered valid C++. These POD-only unions are broken in C++ because they fail to retain a vital invariant they possess in C: any data type can be used as a component type.
To make unions useful, we must allow constructable types as members. This is significant because it is not acceptable to merely assign a component in a constructor body, either of the union itself, or any enclosing struct: you cannot, for example, assign a string to an uninitialised string component.
It follows one must invent some rules for initialising union component with mem-initialisers, for example:
union X { string a; string b; X(string q) : a(q) {} };
But now the question is: what is the rule? Normally the rule is you must initialise every member and base of a class, if you do not do so explicitly, the default constructor is used for the remainder, and if one type which is not explicitly initialised does not have a default constructor, it's an error [Exception: copy constructors, the default is the member copy constructor].
Clearly this rule can't work for unions: the rule has to be instead: if the union has at least one non-POD member, you must explicitly initialise exactly one member in a constructor. In this case, no default constructor, copy constructor, assignment operator, or destructor will be generated and if any of these members are actually used, they must be explicitly supplied.
So now the question becomes: how would you write, say, a copy constructor? It is, of course quite possible to do and get right if you design your union the way, say, X-Windows event unions are designed: with the discriminant tag in each component, but you will have to use placement operator new to do it, and you will have to break the rule I wrote above which appeared at first glance to be correct!
What about default constructor? If you don't have one of those, you can't declare an uninitialised variable.
There are other cases where you can determine the component externally and use placement new to manage a union externally, but that isn't a copy constructor. The fact is, if you have N components you'd need N constructors, and C++ has a broken idea that constructors use the class name, which leaves you rather short of names and forces you to use phantom types to allow overloading to choose the right constructor .. and you can't do that for the copy constructor since its signature is fixed.
Ok, so are there alternatives? Probably, yes, but they're not so easy to dream up, and harder to convince over 100 people that it's worthwhile to think about in a three day meeting crammed with other issues.
It is a pity the committee did not implement the rule above: unions are mandatory for aligning arbitrary data and external management of the components is not really that hard to do manually, and trivial and completely safe when the code is generated by a suitable algorithm, in other words, the rule is mandatory if you want to use C++ as a compiler target language and still generate readable, portable code. Such unions with constructable members have many uses but the most important one is to represent the stack frame of a function containing nested blocks: each block has local data in a struct, and each struct is a union component, there is no need for any constructors or such, the compiler will just use placement new. The union provides alignment and size, and cast free component access.
[And there is no other conforming way to get the right alignment!]
Therefore the answer to your question is: you're asking the wrong question. There's no advantage to POD-only unions being bases, and they certainly can't be derived classes because then they wouldn't be PODs. To make them useful, some time is required to understand why one should follow the principle used everywhere else in C++: missing bits aren't an error unless you try to use them.
Union is a type that can be used as any one of its members depending on which member has been set - only that member can be later read.
When you derive from a type the derived type inherits the base type - the derived type can be used wherever the base type could be. If you could derive from a union the derived class could be used (not implicitly, but explicitly through naming the member) wherever any of the union members could be used, but among those members only one member could be legally accessed. The problem is the data on which member has been set is not stored in the union.
To avoid this subtle yet dangerous contradiction that in fact subverts a type system deriving from a union is not allowed.
Bjarne Stroustrup said 'there seems little reason for it' in The Annotated C++ Reference Manual.
The title asks why unions can't be a base class, but the question appears to be about unions as a derived class. So, which is it?
There's no technical reason why unions can't be a base class; it's just not allowed. A reasonable interpretation would be to think of the union as a struct whose members happen to potentially overlap in memory, and consider the derived class as a class that inherits from this (rather odd) struct. If you need that functionality, you can usually persuade most compilers to accept an anonymous union as a member of a struct. Here's an example, that's suitable for use as a base class. (And there's an anonymous struct in the union for good measure.)
struct V3 {
union {
struct {
float x,y,z;
};
float f[3];
};
};
The rationale for unions as a derived class is probably simpler: the result wouldn't be a union. Unions would have to be the union of all their members, and all of their bases. That's fair enough, and might open up some interesting template possibilities, but you'd have a number of limitations (all bases and members would have to be POD -- and would you be able to inherit twice, because a derived type is inherently non-POD?), this type of inheritance would be different from the other type the language sports (OK, not that this has stopped C++ before) and it's sort of redundant anyway -- the existing union functionality would do just as well.
Stroustrup says this in the D&E book:
As with void *, programmers should know that unions ... are inherently dangerous, should be avoided wherever possible, and should be handled with special care when actually needed.
(The elision doesn't change the meaning.)
So I imagine the decision is arbitrary, and he just saw no reason to change the union functionality (it works fine as-is with the C subset of C++), and so didn't design any integration with the new C++ features. And when the wind changed, it got stuck that way.
I think you got the answer yourself in your comments on EJP's answer.
I think unions are only included in C++ at all in order to be backwards compatible with C. I guess unions seemed like a good idea in 1970, on systems with tiny memory spaces. By the time C++ came along I imagine unions were already looking less useful.
Given that unions are pretty dangerous anyway, and not terribly useful, the vast new opportunities for creating bugs that inheriting from unions would create probably just didn't seem like a good idea :-)
Here's my guess for C++ 03.
As per $9.5/1, In C++ 03, Unions can not have virtual functions. The whole point of a meaningful derivation is to be able to override behaviors in the derived class. If a union cannot have virtual functions, that means that there is no point in deriving from a union.
Hence the rule.
You can inherit the data layout of a union using the anonymous union feature from C++11.
#include <cstddef>
template <size_t N,typename T>
struct VecData {
union {
struct {
float x;
float y;
float z;
};
float a[N];
};
};
template <size_t N, typename T>
class Vec : public VecData<N,T> {
//methods..
};
In general its almost always better not work with unions directly but enclose them within a struct or class. Then you can base your inheritance off the struct outer layer and use unions within if you need to.

Why union can't be used in Inheritance?

I saw below thing in c++ standard (ยง9.5/1):
A union shall not have base classes. A union shall not
be used as a base class.
A union can have member functions
(including constructors and
destructors), but not virtual (10.3)
functions
From above, union can have constructor and destructor as well.
So why is it not allowed in Inheritance ?
EDIT: For answering comments:
If union is allowed as a base class, its data can be used by a derived class. If derived class is interested to use only one member of union, this way can be used for saving memory. I think, this is improper inheritance. Is it better to have union inside derived class in that case ?
If union is allowed as derived class, it can use services of base class. For example, if Union has multiple types of data. As we know, only one type of data can be used. For each type of data, a base class is present to offer services for that particular type. In this case, multiple inheritance can be used to get services of all base classes for all types of data in Union. This also i feel as improper usage of inheritance. But is there any equivalent concept to achieve content in this point?
Just my thoughts...
Here is a simple workaround:
struct InheritedUnion
{
union {
type1 member1;
type2 member2;
};
};
struct InheritsUnion : InheritedUnion
{};
By making the union anonymous, it works just as if the base type were actually a union.
(This answer was written for C++03, the situation may have changed since C++11)
I can't imagine any compelling reason for excluding it... more that there's no particularly good reason for including it. Unions just aren't used enough to matter that much, and there are heavy restrictions on the type of members in the union, restrictions that prevent OO practices. Those restrictions - and the burden of manually tracking the particular variable(s) in a union that have validity - mean pretty much the first thing you want to do with a union is encapsulate it in a class, then you can inherit from that anyway. Letting the union be part of the inheritance chain just spreads the pain around.
So, anything that might give casual C++ users the impression that unions could be mixed into their OO-centric code would cause more trouble than good. Unions are basically a hack for memory conservation, fast-but-nasty data reinterpretation and implementing variants, and tend to be an implementation detail rather than an interface one.
You've added a bit to your question with your edit... thoughts follow.
If union is allowed as a base class, its data can be used by a derived class. If derived class is interested to use only one member of union, this way can be used for saving memory. I think, this is improper inheritance. Is it better to have union inside derived class in that case ?
So, we're discussing:
union U { int i; double d; };
struct D : U { };
U's data members would either have to be - implicitly or explicitly - public, protected or private. If they're public or protected, then they're not encapsulated, and we're back in the "share the pain" scenario mentioned above. U has less ability to encapsulate them than a class containing a union. If they're private, then they could just as easily be a union data member in a class.
If union is allowed as derived class, it can use services of base class. For example, if Union has multiple types of data. As we know, only one type of data can be used. For each type of data, a base class is present to offer services for that particular type. In this case, multiple inheritance can be used to get services of all base classes for all types of data in Union. This also i feel as improper usage of inheritance. But is there any equivalent concept to achieve content in this point?
Ok, this is where things get weird. So, we've got:
union U : public A, private B { };
Firstly, let me be a bit more explicit about something. Unions can't contain complex, encapsulated objects - they're the antithesis of encapsulation. You're pretty much limited to POD data, and can't have non-default constructors etc.. Note I'm talking about the data members of the union, and not the union itself. So, A and B would - if those union-content rules remain - be very limited, and the ability of U to derive not particularly useful.
That leads into the question of why unions can't manage more complex objects in some safe way. Well, how could they do it? Obvious answer is add a hidden enum to say which one is valid, and some rules about which type should be constructed by default, invoking the destructor first when a different enum field is assigned to, etc etc etc.... Maybe they should throw if someone does something to the member that's not currently constructed? Sounds ok?
Well, firstly, the overhead of an enum might not be necessary, as client code might use one member then another in a known-appopriate order. Checks and exceptions in the language itself are a similar overhead... they may be able to be factored down to a single check before multiple uses if left to the client code. In both cases, you'd be paying for some management overhead that only some applications need - a very un-C++ approach.
Ignoring that, unions aren't that simple anyway. Like enums, their use is designed to be flexible and would be hard to communicate to the compiler so it could clean up, check and automate it. You might think "huh? enums are complex?", but each enum is - conceptually generalised - effectively an arbitrary set of independent bitfields of varying width. It's non-trivial to describe which ones are meant to be mutually exclusive or dependent etc.. The compiler doesn't buy into the problem space at all. Similarly, a union may have one or more concurrently legitimate views on the same data, while others are invalid, with subtleties to boot. For example: a union of int64_t, double, and char[4] could always be read as an int64_t or char[4] after being set as a double, but the other way around might read an invalid double and cause undefined behaviour, unless you're re-reading values that came from a double at some earlier time, perhaps in a serialisation/deserialisation library. The compiler doesn't want to buy into the management of that, which is what it would have to do to ensure object members of unions obeyed the promises implicit in their own encapsulation.
You ask "is it better to have union inside derived class?"... no - doesn't generally work as most objects can't be put into a union (see above). You hit this problem whether the union is inside the derived class, or - through the new language features you postulate - the union actually is the derived class.
I do understand your frustration though. In practice, people do sometimes want unions of arbitrary non-trivial objects, so they hack it up the hard and dirty way using reinterpret cast or similar, managing memory alignment of some space big enough for the set of objects they'll support (or - easier but slower - a pointer to them). You'll find this sort of thing in the boost variant and any libraries. But, you can't derive from them... the knowledge about appropriate usage, the extent of safety checks etc. just isn't deducible or expressible in C++. The compiler's not about to do that for you.

Internal typedefs in C++ - good style or bad style?

Something I have found myself doing often lately is declaring typedefs relevant to a particular class inside that class, i.e.
class Lorem
{
typedef boost::shared_ptr<Lorem> ptr;
typedef std::vector<Lorem::ptr> vector;
//
// ...
//
};
These types are then used elsewhere in the code:
Lorem::vector lorems;
Lorem::ptr lorem( new Lorem() );
lorems.push_back( lorem );
Reasons I like it:
It reduces the noise introduced by the class templates, std::vector<Lorem> becomes Lorem::vector, etc.
It serves as a statement of intent - in the example above, the Lorem class is intended to be reference counted via boost::shared_ptr and stored in a vector.
It allows the implementation to change - i.e. if Lorem needed to be changed to be intrusively reference counted (via boost::intrusive_ptr) at a later stage then this would have minimal impact to the code.
I think it looks 'prettier' and is arguably easier to read.
Reasons I don't like it:
There are sometimes issues with dependencies - if you want to embed, say, a Lorem::vector within another class but only need (or want) to forward declare Lorem (as opposed to introducing a dependency on its header file) then you end up having to use the explicit types (e.g. boost::shared_ptr<Lorem> rather than Lorem::ptr), which is a little inconsistent.
It may not be very common, and hence harder to understand?
I try to be objective with my coding style, so it would be good to get some other opinions on it so I can dissect my thinking a little bit.
I think it is excellent style, and I use it myself. It is always best to limit the scope of names as much as possible, and use of classes is the best way to do this in C++. For example, the C++ Standard library makes heavy use of typedefs within classes.
It serves as a statement of intent -
in the example above, the Lorem class
is intended to be reference counted
via boost::shared_ptr and stored in a
vector.
This is exactly what it does not do.
If I see 'Foo::Ptr' in the code, I have absolutely no idea whether it's a shared_ptr or a Foo* (STL has ::pointer typedefs that are T*, remember) or whatever. Esp. if it's a shared pointer, I don't provide a typedef at all, but keep the shared_ptr use explicitly in the code.
Actually, I hardly ever use typedefs outside Template Metaprogramming.
The STL does this type of thing all the time
The STL design with concepts defined in terms of member functions and nested typedefs is a historical cul-de-sac, modern template libraries use free functions and traits classes (cf. Boost.Graph), because these do not exclude built-in types from modelling the concept and because it makes adapting types that were not designed with the given template libraries' concepts in mind easier.
Don't use the STL as a reason to make the same mistakes.
Typedefs are the ones what policy based design and traits built upon in C++, so The power of Generic Programming in C++ stems from typedefs themselves.
Typdefs are definitely are good style. And all your "reasons I like" are good and correct.
About problems you have with that. Well, forward declaration is not a holy grail. You can simply design your code to avoid multi level dependencies.
You can move typedef outside the class but Class::ptr is so much prettier then ClassPtr that I don't do this. It is like with namespaces as for me - things stay connected within the scope.
Sometimes I did
Trait<Loren>::ptr
Trait<Loren>::collection
Trait<Loren>::map
And it can be default for all domain classes and with some specialization for certain ones.
The STL does this type of thing all the time - the typedefs are part of the interface for many classes in the STL.
reference
iterator
size_type
value_type
etc...
are all typedefs that are part of the interface for various STL template classes.
Another vote for this being a good idea. I started doing this when writing a simulation that had to be efficient, both in time and space. All of the value types had an Ptr typedef that started out as a boost shared pointer. I then did some profiling and changed some of them to a boost intrusive pointer without having to change any of the code where these objects were used.
Note that this only works when you know where the classes are going to be used, and that all the uses have the same requirements. I wouldn't use this in library code, for example, because you can't know when writing the library the context in which it will be used.
Currently I'm working on code, that intensively uses these kind of typedefs. So far that is fine.
But I noticed that there are quite often iterative typedefs, the definitions are split among several classes, and you never really know what type you are dealing with. My task is to summarize the size of some complex data structures hidden behind these typedefs - so I can't rely on existing interfaces. In combination with three to six levels of nested namespaces and then it becomes confusing.
So before using them, there are some points to be considered
Does anyone else need these typedefs? Is the class used a lot by other classes?
Do I shorten the usage or hide the class? (In case of hiding you also could think of interfaces.)
Are other people working with the code? How do they do it? Will they think it is easier or will they become confused?
When the typedef is used only within the class itself (i.e. is declared as private) I think its a good idea. However, for exactly the reasons you give, I would not use it if the typedef's need to be known outside the class. In that case I recommend to move them outside the class.
I recommend to move those typedefs outside the class. This way, you remove direct dependency on shared pointer and vector classes and you can include them only when needed. Unless you are using those types in your class implementation, I consider they shouldn't be inner typedefs.
The reasons you like it are still matched, since they are solved by the type aliasing through typedef, not by declaring them inside your class.