I use shared_ptr and STL extensively in the project, and this leads to excessive error-prone types, such as shared_ptr <vector <shared_ptr ā (I am an ObjC programmer by preference where long names are normal, and yet this is too much.) I consider that it would be much clearer to sequentially call this FooListPtr and document the naming convention, Ptr "means shared_ptr and" List "means the vector shared_ptr.
for starters, I recommend using good design structures to define a scope (e.g. namespace), as well as descriptive, non-abbreviated names for typedef. FooListPtr awfully short, imo. no one wants to guess what the abbreviation means (or be surprised that Foo is const, shared, etc.), and no one wants to change their code simply because of collisions with the scope.
it can also help choose a prefix for typedefs in your libraries (as well as other general categories).
it is also a bad idea to drag types from declared scope:
namespace MON { namespace Diddy { class Foo; } typedef Diddy::Foo Diddy_Foo; }
There are exceptions to this:
- fully ecapsualted private type
- contained in a new area
while we are on it, using in the namespace and namespace aliases area should be avoided - qualify the area if you want to minimize future support.
It's easy to typedef, but it causes headaches with headers. It seems that I have several options for defining FooListPtr:
foo.h. This intertwines all the headers and creates serious build problems, so it is not a starter.
this may be an option for ads that really depend on other ads. implying that you need to separate packages, or there is a common localized interface for subsystems.
FooFwd.h ("direct header"). This is what efficient C ++ offers, based on iosfwd.h. This is very consistent, but the overhead of maintaining twice the number of headers is annoying at best.
don't worry about it, really. this is a good practice. the compiler uses advanced declarations and typedefs with very little effort. it is not annoying because it helps to reduce your addictions and helps to ensure their correctness and visibility. there really is no longer need to support it, as other files belong to the "package types" header.
Common.h (put everything together in one file). This kills reusability by mixing up a multitude of unrelated types. Now you canāt just pick up one object and transfer it to another project. This is not a starter.
package-dependent dependencies and inclusions are excellent (ideal, really) - don't rule that out. you will obviously have to create package interfaces (or libraries) that are well designed and structured and represent related component classes. you make an unnecessary problem out of reusing objects / components. Minimize static library data and allow communication and strip phases to complete their tasks. once again so that your packages are small and reusable, and that won't be a problem (assuming your libraries / packages are well designed).
Some kind of bizarre wizard #define, which is typedef if it hasn't been typed yet. I have a constant dislike for the preprocessor, because I think it makes it difficult to find new people with code, but maybe ....
in fact, you can declare a typedef in the same scope several times (for example, in two separate headers) - this is not an error.
Declaring a typedef in the same scope with different base types is a mistake. obviously. you should avoid this, and fortunately, the compiler provides this.
to avoid this, create a ātranslation assemblyā that includes the world ā the compiler will mark type declarations with types that do not match.
trying to sneak with minimal typedefs and / or forwards (which are close enough to free at compilation) is not worth the effort. sometimes you need a bunch of conditional support for forward declarations - as soon as this is determined, it's easy (the stl libraries are a good example of this - if you also send forward template<typename,typename>class vector; ).
Itās best to have all of these ads visible so that you can immediately catch any errors, and you can avoid the preprocessor in this case as a bonus.
Use a vector subclass, not a typedef. It seems dangerous ...
a subclass of std::vector often marked as "beginner error." this container should not be a subclass. don't resort to bad practice just to reduce compilation time / dependency. if the dependency is really that significant, you should probably use PIMPL:
// <package>.types.hpp namespace MON { class FooListPtr; } // FooListPtr.hpp namespace MON { class FooListPtr { /* ... */ private: shared_ptr< vector< shared_ptr<const Foo> > > d_data; }; }
Are there any best practices here? What do they look like in real code when reuse, readability, and consistency are paramount?
Ultimately, I found a small approach based on a compressed package that is best suited for reuse, to reduce compilation time and minimize dependency.