Your design seems workable. However, I won't recommend it. And you didn't mention templates or standard containers.
My feeling is that
it is practically important (for efficiency reasons) to have a lot of (usually small) inline
functions, notably inlined member functions (like getters, setters, etc...), often contained in their class
Class {
.... }
definition.
hence, some of the member functions should be inline
, either inside the class like
class Foo {
int _x;
Foo(int x) : _x(x) {};
~Foo() { _x=0; };
int f(int d) const { return _x + d; };
}
then all of constructor Foo::Foo(int)
, destructor Foo::~Foo
and member function int Foo::f(int)
are inlined
or after the class (usually easier for machine generated code) like
class Foo {
int _x;
inline Foo(int x);
inline ~Foo();
inline int f(int d) const;
};
Foo::Foo(int x) { _x = x; };
Foo::~Foo() { _x = 0; };
int Foo::f(int d) const { return _x+d; };
In both cases you need inlining (or perhaps Link Time Optimization e.g. gcc -flto -O
for compiling & linking) for efficiency reasons.
The compiler can only inline functions when it knows their definition (their body).
then, every time you #include
some class definition. you need to somehow get that inline function definition compiled. Either you put it in the same header, or that header should itself #include
some other file (providing the definition of inlined functions)
In general, especially when using standard C++ library (and using standard containers, so e.g. #include <vector>
) you'll get a lot of system headers (indirectly included). In practice, you don't want very small implementation file (i.e. having a few dozen lines of your source code per file is impractical).
Likewise, existing C++ framework libraries pull a lot of (indirect) headers (e.g. #include <QtGui>
brings a big lot of code).
I suggest having C++ source files (either *.hh
or *.cc
) of a thousand lines each at least.
Look at the size of the preprocessed code, e.g. with g++ -H -C -E
... you'll be scared in practice: even when compiling a small C++ file of a few dozen lines of your source code, you'll have thousands of preprocessed source lines.
Hence my advice of thousand lines source file: any smaller file using the C++ standard library or some C++ framework library (Boost, Qt) is pulling a lot of source lines from indirectly included files.
See also this answer, why Google (with D.Novillo) tries hard to add preparsed headers to GCC, why LLVM/Clang (with C.Latner) wants modules in C and C++. And why Ocaml, Rust, Go, ... have modules...
You could also look at the GIMPLE representation generated by GCC, either using the MELT probe (MELT is a domain specific language to extend GCC, the probe is a simple graphical interface to inspect some internal representations of GCC like Gimple), or using -fdump-tree-all
option to GCC (be careful: that option produces hundreds of dump files). You may also pass -ftime-report to GCC to understand a bit more where it is passing its time when compiling your C++ code.
For machine generated C++ code I recommend even more generating less files, but make them bigger. Generating thousands of small C++ files of a few dozen lines each is inefficient (making the total build time too long): the compiler will spend a lot of time parsing the same #include
-d system headers again and again, and instantiating the same templated types (e.g. when using standard containers) a lot of times.
Remember that C++ permits to have several classes per source file (contrarily to Java (except inner classes)).
Also, if all of your C++ code is generated, you don't really need to generate header files (or you might generate one single big *.hh
) because your generator should know which classes & functions are really used in each generated *.cc
and could generate in that file only those useful declarations and inlined functions definitions.
P.S.: Notice that inline
(like register
) is just a (useful) hint to the compiler. It may avoid inlining a function marked inline
(even implicitly, when inside class
definition). It may also inline some functions not marked inline
. However, a compiler needs to know the body of a function to inline it.