On 14 January 2011 15:39, Achilleas Margaritis wrote:
> 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?

Thank you, Axel. Yes, that's what I meant.



>>
>> 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.

Which is a change to the language semantics!


> 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.

That's a change to how the compiler handles C++ - i.e. a change to the
language semantics.

What part of this are you finding so difficult to understand?

> 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.

A change to how the compiler processes the source code is a change to
the language.  The rules on template instantiation, inline functions,
symbol visibility, inline namespaces etc. would probably all be
affected.

You also don't seem to have considered header dependencies.  If
foo.cpp #includes ten files, some of which are needed for the
interface and some for the implementation, how many of them should be
copied to foo.hpp by your "simple" copy'n'paste?  Should the compiler
analyse which headers are needed just for the interface declarations,
and only include those headers?  Or auto-generate forward-declarations
of all the needed entities?
Or just include all of them, even though some headers may only be
needed for the implementations, resulting in namespace pollution in
other translation units and possible ambiguities, conflicts, or
dependency cycles?

Reply via email to