On Fri, Jan 14, 2011 at 05:39:58PM +0200, Achilleas Margaritis wrote: > > [...] > > There is a violation of the C++-standard: > > - when main.cpp is compiled, the compiler reads "foo.hpp" -- and it > > learns that the class "Foo" has a member-function "bar" which can be > > call from within main.cpp -- so main.cpp is compiled without problem. > > - when "foo.cpp" is compiled, the compiler does not read "foo.hpp" and > > thus it sees that the function "bar" is defined INLINE. So the > > compiler will NOT export Foo::bar() -- it will be impossible to > > link to Foo::bar() from another compilation unit. > > - finally, you try to link both compilation units. Result: main() tries > > to call a function "Foo::bar()" -- but that does not exist ==> > > compilation error. > > On my machine, I get exactly that: > > g++ main.cpp foo.cpp > > /tmp/ccszFpug.o: In function `main': > > main.cpp:(.text+0x27): undefined reference to `Foo::bar()' > > collect2: ld returned 1 exit status > [...] > There is a solution to that: the compiler, knowing that foo::bar is > not an inline function, it does not inline the function but it > automatically compiles the relevant symbol in the foo.o object file. I agree, one can solve it -- but with a change of the language. And for example I use the fact that member-functions which are defined inline ARE inline (e.g. to speedup trivial access functions). > > The trick is to let the compiler know that foo::bar is not an inline > function. The information that foo::bar is not an inline function is > contained in the header, as I've shown: > > foo.hpp: > #ifndef FOO_HPP > #define FOO_HPP > #include <list> > class Foo { > public: > void bar(); > }; > extern std::list<Foo *> foos; > #endif //FOO_HPP > > So, if the compiler was informed about foo::bar not being inlined, it > could then produce the appropriate symbol. This could happen if the > autogenerated header is automatically included when the implementation > file that produced the autogenerated header is compiled. But that is not possible, as in this case you violate the C++-Standard: Adding '#include "foo.hpp"' to foo.cpp in the example results in the fact that class Foo is two times defined, which is illegal C++ -- and in addition, the two definitions differ (once "bar" is inline, once it isn't). So the compiler would need to realize in addition that "foo.hpp" is an autogenerated file -- and thus the compiler would have to use different compilation rules. > > The compiler could check if there is an autogenerated header in the > same folder as the implementation file; if there is, then it is > included automatically in the implementation file. > > Then the compiler manages the clash of symbols as needed. But with that everything becomes much more complex: - When the compiler compiles "foo.cpp" -- how does he already know that there is a "pragma autoinclude" in another file (here: main.cpp)? Either you have to guarantee that "main.cpp" is compiled before "foo.cpp" -- or you have to include the information "foo.hpp will be autogenerated" also in the file "foo.cpp" - How can the compiler detect that the file "foo.hpp" is autgenerated -- and thus a different language-standard has to be used to treat the class "Foo"? (allowing redefinition of the class; ignoring the fact that the two class-definition differ, ...) -- just try adding '#include "foo.hpp"' in the file foo.cpp, this results in: g++ foo.cpp foo.cpp:4: error: redefinition of ‘class Foo’ foo.hpp:6: error: previous definition of ‘class Foo’ - the code is no longer understandable by other compilers: it is impossible to write by hand a "replacement header" with which an unpatched compiler (without this new extension) could compile the code (at least I don't see a possible way)
So I think, this extension would make it necessary at least: - to change the language standard (and add special rules how classes defined in an autogenerated-header are treated) - to add also in "foo.cpp" the information that "foo.hpp" will be autogenerated - to mark "foo.hpp" as being autogenerated And it will be impossible to compile such a code with another compiler (which does NOT know those special rules), even if one supplies by hand the generated header files. Axel