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

Reply via email to