Thanks for replying Daniel,
> > template<class T> void Broken()
> > {
> > assert(sizeof(double) == sizeof(T)); // some code which uses T
>
> This test has an implementation-defined result.
> I know compilers, where sizeof(float) == sizeof(double),
> which is legal, if other constraints are fulfilled.
Yeah, I know, I snipped the real code which is dependent on the type &
then
dispatches another type dependent function. I spotted too that I missed
out
the foo: from the Works/Broken defns after I pushed send... this is a more
representitive works/broken
template<class T> void foo::GetBasic()
{
assert(sz == sizeof(T)); // sz is known, it comes from input byte
sequence
T bas;
/* snip - code fills bas */
pSomeClass->Element(tag, bas);
}
I spotted the problem first because I triggered the assert. Then noticed
it
called the wrong Element() for the type. Then noticed that all GetBasic
were
fixed up to an identical address.
> Because your program has no definitions of foo::Broken
> and foo::Works it violates the ODR, which induces
> undefined behavior. I'm rather sure, that this was not
> the actual tested program
As you say, not the tested program but it shouldn't be undefined (should
it?). The accidental global functions would be ignored & I'd get 2x link
errors as it can't link the foo: versions. As I have "reused" the same fn
names in foo as the globals, foo names trump globals so it would only try
to
link if I used ::Works() or ::Broken(). Not undefined or am I missing your
point?
> Does this program fail to compile? If not, then
Indeed, (VC6 won't build it at all because you can't define a constant in
a
class defn, it thinks = is always a pure virtual fn token!) Intel 4.5
gives
the errors you intend, namely array size must be >0 in the 2 places.
Below is a complete program that exhibits my behaviour, it won't compile
with VC6 (internal compiler error) but will with intel 4.5. The type
function can equally be global or in another class with the same output.
Thanks,
Chris
--------------------------------
#include <iostream>
#include <ostream>
class foo
{
public:
void SomeFN();
template<class T> void Broken();
template<class T> T Works();
template<class T> void Works2(T* dummy);
template<class T> const char* Type(T* dummy);
};
template<class T> void foo::Broken()
{
std::cout << "My name is Broken : " << Type((T*) NULL) << std::endl;
}
template<class T> T foo::Works()
{
std::cout << "My name is Works : " << Type((T*) NULL) << std::endl;
return 1;
}
template<class T> void foo::Works2(T* dummy)
{
std::cout << "My name is Works2 : " << Type((T*) NULL) << std::endl;
}
template<> const char* foo::Type<double>(double* dummy)
{
return "double";
}
template<> const char* foo::Type<float>(float* dummy)
{
return "float";
}
void foo::SomeFN()
{
Broken<float>();
Broken<double>();
Works<float>();
Works<double>();
Works2<float>(NULL);
Works2<double>(NULL);
}
int main() {
foo().SomeFN();
}
---------------------
With output (debug & optimizations on):
My name is Broken : float
My name is Broken : float
My name is Works : float
My name is Works : double
My name is Works2 : float
My name is Works2 : double
Map extract from release build with optimizations on : (only 1 broken)
0001:00001720 ?Works2@[EMAIL PROTECTED]
00402720 f i test.obj
0001:00001ee0 ?Works2@[EMAIL PROTECTED]
00402ee0 f i test.obj
0001:000026a0 ?Works@[EMAIL PROTECTED]
004036a0 f i test.obj
0001:00002e60 ?Works@[EMAIL PROTECTED]
00403e60 f i test.obj
0001:00003620 ?Broken@[EMAIL PROTECTED]
00404620 f i test.obj
--
[ See http://www.gotw.ca/resources/clcm.htm
for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


|