POV-Ray : Newsgroups : povray.off-topic : A question about Java generics (not a flame) : Re: A question about Java generics (not a flame) Server Time
7 Sep 2024 19:17:54 EDT (-0400)
  Re: A question about Java generics (not a flame)  
From: Warp
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

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