This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/14318] New: sizeof() does too much
- From: "s_gccbugzilla at nedprod dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 27 Feb 2004 03:26:27 -0000
- Subject: [Bug c++/14318] New: sizeof() does too much
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
I appreciate that some may not consider this a bug, but the code below is an
Alexandrescu style method of determining convertibility which fails on GCC v3.4
and v3.2.2. It does not fail on MSVC7.1 and I would assume other compilers Loki
runs on. It does not fail on GCC when the type is not a 64 bit integer (this
smells fishy).
[ned@katey TClient]$ g++ test1.cpp
test1.cpp: In function `int main()':
test1.cpp:48: conversion from `Foo' to `long int' is ambiguous
test1.cpp:9: candidates are: Foo::operator long long int&()
test1.cpp:10: Foo::operator long long int() const
test1.cpp:11: Foo::operator double()
test1.cpp:12: Foo::operator double() const
test1.cpp:13: Foo::operator bool()
test1.cpp:14: Foo::operator bool() const
test1.cpp: At global scope:
test1.cpp: In instantiation of `convertible<long unsigned int, Foo>':
test1.cpp:53: instantiated from here
test1.cpp:53: warning: cannot pass objects of non-POD type `class Foo' through
`...'; call will abort at runtime
Here's the code:
/* Test for implicit conversion bug */
#include <stdio.h>
class Foo
{
long long int data; // Works fine if is "long int" or "short int" etc
public:
Foo(long long int a) : data(a) { }
operator long long int &() throw() { return data; }
operator long long int() const throw() { return data; }
operator double() throw() { return (double) data; }
operator double() const throw() { return (double) data; }
operator bool() throw() { return data!=0; }
operator bool() const throw() { return data!=0; }
};
namespace convertiblePrivate {
template<typename to, typename from> struct impl
{
struct TwoChar { char foo[2]; };
static from &makeFrom();
static TwoChar test(...);
static char test(to);
};
}
/*! \struct convertible
\ingroup generic
\brief Returns true if \em from can become \em to
*/
template<typename to, typename from> struct convertible
{
private:
typedef convertiblePrivate::impl<to, from> impl;
public:
enum { value=sizeof(impl::test(impl::makeFrom()))==sizeof(char) };
};
template<typename T> struct convertible<void, T> { enum { value=false }; };
template<typename T> struct convertible<T, void> { enum { value=false }; };
template<> struct convertible<void, void> { enum { value=true }; };
int main(void)
{
long int a;
double b;
bool c;
Foo f(5);
a=f;
b=f;
c=f;
printf("a=%ld, b=%lf, c=%d\n", a, b, c);
c=convertible<unsigned long int, Foo>::value;
return 0;
}
The trouble is that the metaprogramming code to determine convertibility gets
tripped up when asked if it can convert to a nearly similar type but ONLY when
it's either a signed long long or an unsigned long long. This does NOT affect
normal integers.
In this case, I don't care. The code is to determine convertibility so I can
/avoid/ compiling bad code via specialisation. The fact it trips up on the test
negates the whole point of the exercise!
If sizeof() did less, it also wouldn't raise the warning about POD types going
through ... - this doesn't matter as no actual code actually does this here (it
being inside a sizeof().
Thoughts?
Cheers,
Niall
--
Summary: sizeof() does too much
Product: gcc
Version: 3.4.0
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: s_gccbugzilla at nedprod dot com
CC: gcc-bugs at gcc dot gnu dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14318