POV-Ray : Newsgroups : povray.off-topic : A question about Java generics (not a flame) Server Time
7 Sep 2024 17:15:38 EDT (-0400)
  A question about Java generics (not a flame) (Message 54 to 63 of 63)  
<<< Previous 10 Messages Goto Initial 10 Messages
From: Fredrik Eriksson
Subject: Re: A question about Java generics (not a flame)
Date: 15 May 2008 13:06:12
Message: <op.ua7ggm1d7bxctx@e6600>
On Thu, 15 May 2008 14:49:55 +0200, Warp <war### [at] tagpovrayorg> wrote:
> Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
>> Now make a small change to main.cpp:
>
>> // main.cpp
>>    export template <typename T> void f();
>
>>    #include "g.hpp"
>>    template <> void g(int i) { /* Do something completely different */ }
>
>>    int main(){ f<int>(); }
>> // end main.cpp
>
>   I don't see how this causes a problem described earlier. This simply
> requires main.cpp to be recompiled (after all, it's the one which has
> been changed), which will result in a new object file which does not
> use the export template.

What? The exported template 'f' is still used. Only 'g' is changed.


>   Why would this cause the need to recompile the export template for
> each usage in the program?

It forces the exported template to be recompiled whenever you change any  
translation unit that instantiates it.



-- 
FE


Post a reply to this message

From: Fredrik Eriksson
Subject: Re: A question about Java generics (not a flame)
Date: 15 May 2008 13:11:45
Message: <op.ua7gptbl7bxctx@e6600>
On Thu, 15 May 2008 18:12:17 +0200, Warp <war### [at] tagpovrayorg> wrote:
>> foo.cc:
>> export template<typename T>
>> void foo(T t) { bar(t); }
>
>>   I see how that could make some difference.
>
>   OTOH, thinking about it: There's no function named 'bar' defined  
> anywhere in the scope of foo.cc, so why should that even compile?

'bar' is a dependent name, and must therefore be looked up in both the  
definition context and the instantiation context.



>   I have to admit I don't know if the C++ standard requires the  
> environment of the instantation of the template when compiling the
> template function or not.

When parsing the template definition, only non-dependent names are looked  
up. Dependent names are looked up at the instantiation point; at that  
point both contexts are needed.



-- 
FE


Post a reply to this message

From: Warp
Subject: Re: A question about Java generics (not a flame)
Date: 16 May 2008 02:46:09
Message: <482d2db1@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
> foo.cc:
> export template<typename T>
> void foo(T t) { bar(t); }


> a.cc:
> export template<typename T>
> void foo(T t);

> void bar(int i);

> void a() { foo(5); }


> b.cc:
> export template<typename T>
> void foo(T t);

> void bar(long i);

> void b() { foo(5); }


>   I see how that could make some difference.

  Actually this isn't as simple after all. I made some tests with gcc,
and I'm getting rather curious results.

  In one file I have this:

// ----- file1.cc -----
#include <iostream>

template<typename T>
void foo(T t)
{
    bar(t);
}

void bar(int i) { std::cout << "int: " << i << std::endl; }

void b();

int main()
{
    foo(5);
    b();
}
// --------------------

  And in another file I have this:

// ----- file2.cc -----
#include <iostream>

template<typename T>
void foo(T t)
{
    bar(t);
}

void bar(long i) { std::cout << "long: " << i << std::endl; }

void b()
{
    foo(7);
}
// --------------------

  When I run this program I get the expected result:

int: 5
long: 7

  However, this happens because gcc is inlining the template function in
both cases. If I stop it from being able to inline the function, curious
things happen. This can be done, for example, by adding a static variable
inside the function, so that the function becomes, in both cases:

template<typename T>
void foo(T t)
{
    static int count = 0;
    std::cout << "count: " << ++count << std::endl;
    bar(t);
}

  Now, what do you think the output is? Rather surprisingly:

count: 1
int: 5
count: 2
int: 7

  Which one of the two instances of foo() is called depends on which .cc
file is specified first. The other one is ignored.

  This is even so if the implementations of foo() are different (which answers
that question). For example, if I make the one in the first file like this:

template<typename T>
void foo(T t)
{
    static int count = 0;
    std::cout << "count(1): " << ++count << std::endl;
    bar(t);
}

and the second one like this:

template<typename T>
void foo(T t)
{
    static int count = 0;
    std::cout << "count(2): " << ++count << std::endl;
    bar(t);
}

the output will be:

count(1): 1
int: 5
count(1): 2
int: 7

  Only the first foo() function is used, the second one is completely
ignored.

  I have to admit I don't know if gcc is behaving correctly here. However,
I can see how this could be the case also with export templates: Even if
the context of the instantiation changes, it might not matter. It may still
be so that only one instantiation is used throughout the program (and thus
the export template has to be compiled once even if it's instantiated several
times).

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: A question about Java generics (not a flame)
Date: 16 May 2008 09:16:07
Message: <482d8917@news.povray.org>
Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
> >   I have to admit I don't know if the C++ standard requires the  
> > environment of the instantation of the template when compiling the
> > template function or not.

> When parsing the template definition, only non-dependent names are looked  
> up. Dependent names are looked up at the instantiation point; at that  
> point both contexts are needed.

  Actually that's not what the C++ standard says. This is the relevant
part of the standard:

    A specialization for a function template, a member
    function template, or of a member function or static
    data member of a class template may have multiple points
    of instantiations within a translation unit. A
    specialization for a class template has at most one
    point of instantiation within a translation unit. A
    specialization for any template may have points of
    instantiation in multiple translation units. If two
    different points of instantiation give a template
    specialization different meanings according to the one
    definition rule (3.2), the program is ill-formed, no
    diagnostic required.

  In short: If the context causes a template instantiation to produce
different results, the program is ill-formed. In other words, the
result is undefined behavior, and the compiler can do whatever it wants.

  I understand this to also mean that the compiler is allowed to compile
an export template just once even if it's instantiated at several places,
using the context of one of those places.

-- 
                                                          - Warp


Post a reply to this message

From: Fredrik Eriksson
Subject: Re: A question about Java generics (not a flame)
Date: 16 May 2008 13:16:11
Message: <op.ua9bk8kz7bxctx@e6600.bredbandsbolaget.se>
On Fri, 16 May 2008 15:16:07 +0200, Warp <war### [at] tagpovrayorg> wrote:
> Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
>> When parsing the template definition, only non-dependent names are  
>> looked
>> up. Dependent names are looked up at the instantiation point; at that
>> point both contexts are needed.
>
>   Actually that's not what the C++ standard says.

Oh yes it is. Check sections 14.6.3 & 14.6.4.



> This is the relevant part of the standard:
>
>     A specialization for a function template, a member
>     function template, or of a member function or static
>     data member of a class template may have multiple points
>     of instantiations within a translation unit. A
>     specialization for a class template has at most one
>     point of instantiation within a translation unit. A
>     specialization for any template may have points of
>     instantiation in multiple translation units. If two
>     different points of instantiation give a template
>     specialization different meanings according to the one
>     definition rule (3.2), the program is ill-formed, no
>     diagnostic required.
>
>   In short: If the context causes a template instantiation to produce
> different results, the program is ill-formed. In other words, the
> result is undefined behavior, and the compiler can do whatever it wants.

What the paragraph (from section 14.6.4.1) says is that if a particular  
template specialisation is instantiated in more than one place then those  
instantiations must have the same meaning.

In the example I posted there is only one instantiation point for 'f'; the  
ODR is irrelevant there.



>   I understand this to also mean that the compiler is allowed to compile
> an export template just once even if it's instantiated at several places,
> using the context of one of those places.

Only if all those places use the exact same template specialisation. Note  
that this would require the compiler/linker to remember which translation  
units use which exported templates, since the exported template must still  
be recompiled if all of the relevant contexts change. Also note that the  
linker would have to verify that at least one of the translation units  
having an "unchanged" context actually gets linked in; if not, the  
template would have to be recompiled.



-- 
FE


Post a reply to this message

From: Fredrik Eriksson
Subject: Re: A question about Java generics (not a flame)
Date: 16 May 2008 13:28:46
Message: <op.ua9b57dj7bxctx@e6600.bredbandsbolaget.se>
On Fri, 16 May 2008 08:46:09 +0200, Warp <war### [at] tagpovrayorg> wrote:
> Warp <war### [at] tagpovrayorg> wrote:
>
>   In one file I have this:
>
> // ----- file1.cc -----
> #include <iostream>
>
> template<typename T>
> void foo(T t)
> {
>     bar(t);
> }
>
> void bar(int i) { std::cout << "int: " << i << std::endl; }
>
> void b();
>
> int main()
> {
>     foo(5);
>     b();
> }
> // --------------------
>
>   And in another file I have this:
>
> // ----- file2.cc -----
> #include <iostream>
>
> template<typename T>
> void foo(T t)
> {
>     bar(t);
> }
>
> void bar(long i) { std::cout << "long: " << i << std::endl; }
>
> void b()
> {
>     foo(7);
> }
> // --------------------

Your example is ill-formed according to the very paragraph you yourself  
quoted in another post. You have multiple instantiations of 'foo<int>',  
but they have different meanings. Also, since the overloads of 'bar' are  
spread out, section 14.6.4.2 applies as well:

"If the call would be ill-formed or would find a better match had the  
lookup within the associated namespaces considered all the function  
declarations with external linkage introduced in those namespaces in all  
translation units, not just considering those declarations found in the  
template definition and template instantiation contexts, then the program  
has undefined behavior."



>   I have to admit I don't know if gcc is behaving correctly here.

In this case it does not matter, as the example is ill-formed. Note  
however that few C++ compilers correctly implement two-phase lookup.



-- 
FE


Post a reply to this message

From: Warp
Subject: Re: A question about Java generics (not a flame)
Date: 17 May 2008 04:36:31
Message: <482e990e@news.povray.org>
Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
> >   I understand this to also mean that the compiler is allowed to compile
> > an export template just once even if it's instantiated at several places,
> > using the context of one of those places.

> Only if all those places use the exact same template specialisation. Note  
> that this would require the compiler/linker to remember which translation  
> units use which exported templates, since the exported template must still  
> be recompiled if all of the relevant contexts change. Also note that the  
> linker would have to verify that at least one of the translation units  
> having an "unchanged" context actually gets linked in; if not, the  
> template would have to be recompiled.

  Sorry, I still don't understand this.

  I tried my foo-bar example making the bar() function a template which was
specialized in one of the compilation units but not the other, and at least
gcc still behave in the same way: When foo() was not inlined, only one
version of bar() was called: The specialized version was never called.

  From what you have written it sounds like the compiler would have to
always call the specialized bar() template if it is in the context of
the foo() instantiation, but at least gcc doesn't behave this way (and,
frankly, I don't know *how* it could behave that way without seriously
messing things up).

-- 
                                                          - Warp


Post a reply to this message

From: Fredrik Eriksson
Subject: Re: A question about Java generics (not a flame)
Date: 17 May 2008 05:52:26
Message: <op.ubalpng87bxctx@e6600.bredbandsbolaget.se>
On Sat, 17 May 2008 10:36:31 +0200, Warp <war### [at] tagpovrayorg> wrote:
>   Sorry, I still don't understand this.
>
>   I tried my foo-bar example making the bar() function a template which  
> was
> specialized in one of the compilation units but not the other, and at  
> least
> gcc still behave in the same way: When foo() was not inlined, only one
> version of bar() was called: The specialized version was never called.

Your foo-bar example is ill-formed. The compiler can do whatever it wants.



>   From what you have written it sounds like the compiler would have to
> always call the specialized bar() template if it is in the context of
> the foo() instantiation, but at least gcc doesn't behave this way (and,
> frankly, I don't know *how* it could behave that way without seriously
> messing things up).

It is commonly called "two-phase lookup" (though it is not named as such  
in the standard) and is explained in section 14.6 [temp.res] of the  
standard. Section 14.6.4 [temp.dep.res] deals specifically with dependent  
name resolution.

Compiler writers have been rather slow in implementing two-phase lookup  
properly, almost as slow as with implementing 'export'.



-- 
FE


Post a reply to this message

From: Warp
Subject: Re: A question about Java generics (not a flame)
Date: 17 May 2008 07:41:18
Message: <482ec45e@news.povray.org>
Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
> On Sat, 17 May 2008 10:36:31 +0200, Warp <war### [at] tagpovrayorg> wrote:
> >   Sorry, I still don't understand this.
> >
> >   I tried my foo-bar example making the bar() function a template which  
> > was
> > specialized in one of the compilation units but not the other, and at  
> > least
> > gcc still behave in the same way: When foo() was not inlined, only one
> > version of bar() was called: The specialized version was never called.

> Your foo-bar example is ill-formed. The compiler can do whatever it wants.

  How is it different from your example, which you gave earlier? Also you
had a template function calling another template function, and the latter
being specialized in the context of instantiating the former. That's exactly
what I did.

-- 
                                                          - Warp


Post a reply to this message

From: Fredrik Eriksson
Subject: Re: A question about Java generics (not a flame)
Date: 17 May 2008 07:56:24
Message: <op.ubarf9o57bxctx@e6600.bredbandsbolaget.se>
On Sat, 17 May 2008 13:41:18 +0200, Warp <war### [at] tagpovrayorg> wrote:
> Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
>> Your foo-bar example is ill-formed. The compiler can do whatever it  
>> wants.
>
>   How is it different from your example, which you gave earlier? Also you
> had a template function calling another template function, and the latter
> being specialized in the context of instantiating the former. That's  
> exactly what I did.


The difference is that you are instantiating 'foo<int>' in more than one  
place. When you do that, the instantiations must have the same meaning or  
the program is ill-formed. In my example 'f<int>' is only instantiated  
once. That example was intented only to demonstrate why an exported  
template must be recompiled when code that uses it is changed.



-- 
FE


Post a reply to this message

<<< Previous 10 Messages Goto Initial 10 Messages

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.