Talk About Network

Google


Register and Login
Nick
Password
Register create new account Sign up is FREE and you can post replies, new topics, bookmark posts and more!
Recover lost password


Programming > C++ Moderated > Re: Template fu...
Latest [ Topics | Posts ] Archive Post A New Topic Post a Reply
<< Topic < Post Post 2 of 4 Topic 9576 of 9828
Post > Topic >>

Re: Template function problem language or compiler bug?

by =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@[EMAIL PROTECTED] May 7, 2008 at 06:32 PM

On 7 Mai, 19:43, "Chris Morley" <chris.mor...@[EMAIL PROTECTED]
> wrote:
> I found a bit of a weirdo using Intel 4.5 compiler & I've seen similar
bad
> stuff in VC6. I don't know if it is a language 'feature' or a bug in the
> compiler's template handling - the compilers are old.
>
> Basically I have a template function (as a member in a class) with void
> return & argument. To use the function you have to explicitly tell the
> compiler what type - or the compiler errors (reasonable as it can't
> determine the type!). The linked program then uses the first type
> encountered for all links to that function (i.e. _same_ address)
regardless
> of they type provided! To fix it, if I declare a return type of the
template
> type instead of void, it links the explicitly defined function
correctly! Is
> this a bug with "template<class T> void fn(void) hadnling by this
compiler
> or a language feature in all C++ compilers? (feels like a name
> mangling/linker bug to me)
>
> Chris
>
> e.g.
>
> HEADER
>
> class foo
> {
> public:
>      void SomeFN();
>      template<class T> void Broken();
>      template<class T> T Works();

OK, these are member functions.

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

> }
>
> template<class T> T Works()
> {
>      assert(sizeof(double) == sizeof(T)); // some code which uses T
>      return 1;
> }

And these are not.

> void foo:SomeFN()
> {
>      Broken<float>(); // ok, type is float in expanded fn
>      Broken<double>();  // broken, type is also float!
>      Works<float>(); // ok, type is float
>      Works<double>(); // ok, type is double
> }

Note that above program will *never* attempt to invoke
the above defined *free* functions Broken and Works.
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, but we could legally stop
here with the analysis ;-)

Because this would be a bit too simple ;-), let's first
transform it into a syntactically valid program which
obeys the ODR where we use a safe test and where we also
ensure that the test happens during compile-time, which
eases the diagnostics:

template<typename T>
struct is_double {
   static const bool value = false;
};

template<>
struct is_double<double> {
   static const bool value = true;
};

class foo
{
public:
      void SomeFN();
      template<class T> void Broken();
      template<class T> T Works();
};

template<class T> void foo::Broken()
{
   typedef bool test[is_double<T>::value ? 1 : -1];
}

template<class T> T foo::Works()
{
   typedef bool test[is_double<T>::value ? 1 : -1];
   return 1;
}

void foo::SomeFN()
{
   Broken<float>(); // Should fail to compile
   Broken<double>();  // Should be accepted
   Works<float>(); // Should fail to compile
   Works<double>(); // Should be accepted
}

int main() {
   foo().SomeFN();
}

Does this program fail to compile? If not, then
this is a compiler defect. And this defect is probably
an optimization error, because it is well-known, that
some compilers 'merge' different templates instantiations
into one entity. If this is done, without causing
observable behaviour, this is indeed a valid
technique. E.g. if your actual definitions of foo::Works
and foo::Broken would have been written this
way:

#include <iostream>
#include <ostream>

template<class T> void foo::Broken()
{
   std::cout << "My name is Broken" << std::endl;
}

template<class T> T foo::Works()
{
   std::cout << "My name is Works" << std::endl;
   return 1;
}

than the compiler could perform this technique,
because you could not observe the difference with
your program above. *But* if you have used your
assert test with my is_double predicate *and* if
you have *not* defined NDEBUG, then you have
a program, which leads to observable behaviour
according to the standard, which can be deduced
from the following quotations from the current C++
standard:

[intro.execution]/6:
"The observable behavior of the abstract machine is
its sequence of reads and writes to volatile data and
calls to library I/O functions."

and the C standard (unfortunately I have only the
C99 standard available):

7.2.1.1/2: (The assert macro)
"[..] When it is executed, if expression [..] is false [..],
the assert macro writes information about the particular call
that failed [..] on the standard error stream in an
implementation-defined format. It then calls the abort function."

So, if the program compiles and runs successfully,
it violates the C++ standard.

HTH & Greetings from Bremen,

Daniel Krügler


-- 
      [ See http://www.gotw.ca/resources/clcm.htm
for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]
 




 4 Posts in Topic:
Template function problem language or compiler bug?
"Chris Morley"   2008-05-07 11:43:27 
Re: Template function problem language or compiler bug?
=?ISO-8859-1?Q?Daniel_Kr=  2008-05-07 18:32:18 
Re: Template function problem language or compiler bug?
"Chris Morley"   2008-05-08 09:13:28 
Re: Template function problem language or compiler bug?
=?ISO-8859-1?Q?Daniel_Kr=  2008-05-08 21:29:57 

Post A Reply:
  Go here to Signup

AddThis Feed Button


About - Advertising - Contact - Frequently Asked Questions - Privacy Policy - Terms of Use - Signup

Contact
tan12V112 Thu Jul 24 16:00:00 CDT 2008.