J
Juha Nieminen
Let's assume we have one .cc file which contains the following:
// ----------- file 1 -----------
#include <iostream>
template<typename T>
void foo(T t) { bar(t); }
void bar(int i) { std::cout << "int: " << i << std::endl; }
void anotherFunc();
int main() { foo(5); anotherFunc(); }
// ------------------------------
And another file which contains the following:
// ----------- file 2 -----------
#include <iostream>
template<typename T>
void foo(T t) { bar(t); }
void bar(long i) { std::cout << "long: " << i << std::endl; }
void anotherFunc() { foo(7); }
// ------------------------------
When I compile and run this, I get:
int: 5
long: 7
The two instances of foo() are calling different bar() functions,
depending on the context. I assume this is because gcc is inlining the
foo() function.
However, if I stop gcc from inlining foo(), for example by adding a
static variable inside it, a curious thing happens. That is, if I
convert both foo() functions into this:
// ------------------------------
template<typename T>
void foo(T t)
{
static int count = 0;
std::cout << "count: " << ++count << std::endl;
bar(t);
}
// ------------------------------
then the output becomes:
count: 1
int: 5
count: 2
int: 7
Clearly the second foo() is being completely ignored (by the linker).
This can be confirmed by making the foo() functions different. For
example, if I make the second foo() function like this:
template<typename T>
void foo(T t)
{
static int count = 0;
std::cout << "count(2): " << ++count << std::endl;
bar(t);
}
it doesn't matter: Still the same output. (Curiously gcc never complains
that the two implementations of foo() are different.)
Which one of the two foo() function is used seems to depend on which
..cc file is given to gcc first. If I change their order I get:
count(2): 1
long: 5
count(2): 2
long: 7
Now the first foo() is being completely ignored.
So my question is: Is this behavior (ie. the inconsistent behavior of
these template functions depending on whether they are inlined or not)
standard-conforming, is it Undefined Behavior(TM), or is it a bug in gcc?
Another question: Assuming this is standard-conforming, do export
templates work in this same manner? (In other words, is an export
template instantiated in one context, and all other possible
instantiations of that template use that one?)
// ----------- file 1 -----------
#include <iostream>
template<typename T>
void foo(T t) { bar(t); }
void bar(int i) { std::cout << "int: " << i << std::endl; }
void anotherFunc();
int main() { foo(5); anotherFunc(); }
// ------------------------------
And another file which contains the following:
// ----------- file 2 -----------
#include <iostream>
template<typename T>
void foo(T t) { bar(t); }
void bar(long i) { std::cout << "long: " << i << std::endl; }
void anotherFunc() { foo(7); }
// ------------------------------
When I compile and run this, I get:
int: 5
long: 7
The two instances of foo() are calling different bar() functions,
depending on the context. I assume this is because gcc is inlining the
foo() function.
However, if I stop gcc from inlining foo(), for example by adding a
static variable inside it, a curious thing happens. That is, if I
convert both foo() functions into this:
// ------------------------------
template<typename T>
void foo(T t)
{
static int count = 0;
std::cout << "count: " << ++count << std::endl;
bar(t);
}
// ------------------------------
then the output becomes:
count: 1
int: 5
count: 2
int: 7
Clearly the second foo() is being completely ignored (by the linker).
This can be confirmed by making the foo() functions different. For
example, if I make the second foo() function like this:
template<typename T>
void foo(T t)
{
static int count = 0;
std::cout << "count(2): " << ++count << std::endl;
bar(t);
}
it doesn't matter: Still the same output. (Curiously gcc never complains
that the two implementations of foo() are different.)
Which one of the two foo() function is used seems to depend on which
..cc file is given to gcc first. If I change their order I get:
count(2): 1
long: 5
count(2): 2
long: 7
Now the first foo() is being completely ignored.
So my question is: Is this behavior (ie. the inconsistent behavior of
these template functions depending on whether they are inlined or not)
standard-conforming, is it Undefined Behavior(TM), or is it a bug in gcc?
Another question: Assuming this is standard-conforming, do export
templates work in this same manner? (In other words, is an export
template instantiated in one context, and all other possible
instantiations of that template use that one?)