Best example header files for typedefs

I use shared_ptr and STL in the project, and this leads to excessive error-prone types, for example shared_ptr< vector< shared_ptr<const Foo> > > >>> (I am an ObjC programmer by preference where long names are normal, and it's too much anyway. ) I suppose it would be much clearer to call it FooListPtr and document a naming convention that ā€œPtrā€ means shared_ptr and ā€œListā€ means the vector shared_ptr.

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 does not start.
  • 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 headings is annoying at best.
  • 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.
  • Some kind of bizarre wizard #define, which is typedef if it hasn't been changed yet. I have a constant dislike for the preprocessor, because I think it makes it difficult to find new people with code, but maybe ...
  • Use a vector subclass, not a typedef. It seems dangerous ...

Are there any best practices here? What do they look like in real code when reuse, readability, and consistency are paramount?

I added this community wiki if others want to add additional options for discussion.

+50
c ++ typedef
Mar 01 '10 at 14:45
source share
5 answers

I am programming a project that sounds like it uses the common.h method. It works great for this project.

There is a file called ForwardsDecl.h , which is located in the precompiled header and simply forwards all the important classes and the necessary typedef. In this case, unique_ptr used instead of shared_ptr , but the use should be similar. It looks like this:

 // Forward declarations class ObjectA; class ObjectB; class ObjectC; // List typedefs typedef std::vector<std::unique_ptr<ObjectA>> ObjectAList; typedef std::vector<std::unique_ptr<ObjectB>> ObjectBList; typedef std::vector<std::unique_ptr<ObjectC>> ObjectCList; 

This code is accepted by Visual C ++ 2010, even if classes are only declared ahead (full class definitions are not needed, so there is no need to include the header file of each class). I don’t know if this standard and other compilers will require a full definition of the class, but it’s useful that it is not: another class (ObjectD) can have an ObjectAList as a member, without having to include ObjectA.h - this can really help reduce the dependencies of the header files !

Maintenance is not a particular problem, because forward declarations need only be written once, and any subsequent changes should only occur in the full declaration in the class header file (and this will result in recompilation of fewer source files due to reduced dependencies).

Finally, it seems that this can be shared between projects (I have not tried it myself), because even if the project does not actually declare ObjectA, it does not matter, because it was declared forward only and if you do not use its compiler anyway. Therefore, the file may contain class names in all projects in which it was used, and it does not matter if some are missing for a particular project. All that is required is the required complete declaration header (e.g. ObjectA.h ), which is included in any source files (.cpp) that actually use them.

+12
Oct 26 '10 at 21:10
source share

I would use a combined forward header approach and a kind of common.h header that is specific to your project and includes all direct declaration headers and any other things that are general and easy.

You complain about the overhead of maintaining twice the number of headers, but I don't think this should be too much of a problem: front headers usually need to know only a very limited number of types (one?), And sometimes not even the full type.

You can even try to auto-generate headers using a script (this is done, for example, in SeqAn ), if there really is that many headers.

+6
Mar 01
source share

+1 for documenting typedef conventions.

  • Foo.h - can you elaborate on the problems you have?
  • FooFwd.h - I would not use them at all, only on "obvious hot spots." (Yes, ā€œhot spotsā€ are difficult to determine). It does not change the IMO rules because when you enter the fwd header, the associated typedefs from foo.h are moved there.
  • Common.h - cool for small projects, but not scalable, I agree.
  • Some freaky #define ... PLEASE NO! ...
  • Using a vector subclass does not make it better. However, you can use deterrence.

So here are the preliminary suggestions (revised from this other question ..)

  • Headers of the standard type <boost/shared_ptr.hpp> , <vector> , etc. can enter the precompiled header / share file for the project. It's not bad. (I personally still add them where necessary, but this works in addition to putting them on PCH.)

  • If the container is an implementation detail, then the typedef is sent to where the container is declared (for example, private members of a class if the container is a private member of the class).

  • Associated types (e.g. FooListPtr ) go where Foo is declared , if the associated type is the main use type. This is almost always true for some types - for example, shared_ptr .

  • If Foo gets a separate direct access declaration header, and the corresponding type is okay with it, it also moves to FooFwd.h.

  • If the type is associated only with a specific interface (for example, a parameter for a public method), it goes there.

  • If the type is generic (and does not meet any of the previous criteria), it gets its own header. Please note that this also means involving all the dependencies.

It feels ā€œobviousā€ to me, but I agree that this is not good as the coding standard.

+4
Mar 01 '10 at 17:29
source share

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; } /* << Diddy */ /*...*/ typedef Diddy::Foo Diddy_Foo; } /* << MON */ 

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.

+2
Oct 26 '10 at 22:11
source share

Unfortunately, with typedefs, you need to choose not ideal options for your header files. There are special cases where option 1 (right in the class header) works well, but it doesn't seem to work for you. There are also cases where the latter option works well, but is usually used when you use a subclass to replace a template that includes a class with one member of type std :: vector. For your situation, I would use forward header declaration. There's extra typing and overhead, but it won't be C ++ otherwise, right? This keeps things separate, clean and fast.

+1
Mar 01
source share



All Articles