On Fri, Jan 14, 2011 at 5:29 PM, Axel Freyn <axel-fr...@gmx.de> wrote:
> On Fri, Jan 14, 2011 at 05:17:12PM +0200, Achilleas Margaritis wrote:
>> On Fri, Jan 14, 2011 at 4:58 PM, Jonathan Wakely <jwakely....@gmail.com> 
>> wrote:
>> > On 14 January 2011 13:26, Achilleas Margaritis wrote:
>> >> My proposal does not change the language in any way, it only is a
>> >> copy-and-paste job.
>> >
>> > That's not true, your example with an inline member function
>> > demonstrates that the compiler must be changed to support your
>> > proposal, so that functions defined inline are given a non-inline
>> > definition that can be linked to by other translation units.
>> >
>> > If it was a copy'n'paste job, it could be done by an external tool,
>> > which you've disputed.
>>
>> My proposal doesn't change anything of the language from the
>> programmer's perspective.
> I think the point Jonathan wanted to make is the following: your
> original example does not compile -- and can not compile without a
> change of the language. If you create by hand the auto-include file you
> proposed:
>
> main.cpp:
> #include "foo.hpp"
> int main() {
>  Foo *foo = new Foo;
>  foo->bar();
>  foos.push_back(foo);
> }
>
> foo.cpp:
> #include <list>
> class Foo {
>  public:
>    void bar() {}
> };
> std::list<Foo *> foos;
> static int data = 0;
>
> foo.hpp:
> #ifndef FOO_HPP
> #define FOO_HPP
> #include <list>
> class Foo {
>  public:
>    void bar();
> };
> extern std::list<Foo *> foos;
> #endif //FOO_HPP
>
> 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
>
> So in fact you have to change the language, I believe (at least it is
> necessary to remove the rule "if a member function is defined inline in
> a class, it is marked as "inline" and NOT exported"). But may be there
> are also other problems?
>
> HTH,
>
> Axel
>

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.

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.

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.

>From the programmer's language perspective, it is not a change in the language.

Reply via email to