EDG possible sozeof BUG

R

Rob Williscroft

I have the following code , part of a trait to detect wether a type
has a member operator "Type" (), it works fine with g++ 3.4 (msvc
compiles it but it doesn't work for template'd operator T ()) but
with CBuilderX (EDG frontend) and Comeau's online compiler I get:

test.cpp:23: error invalid type conversion detected during
instantiation of "X::eek:perator T() [with T=int &]" at line 41

I.e it instantiates X::eek:perator< int & > int & () inside the
sizeof, any other compiler than EDG and I'd automaticly think
this was a compiler bug.

Thought's ?

#include <iostream>
#include <iomanip>

template < typename T, typename Type >
struct has_conversion_operator
{
private:
template < typename V, Type (V::*M)() > struct empty_t_;
template < typename U >
static char helper_f( empty_t_< U, &U::eek:perator Type > * );
template < typename U >
static char (&helper_f( ... ))[2];

public:
static bool const bool_value =
( sizeof( helper_f< T >( 0 ) ) == sizeof( char ) )
;
};

struct X
{
template < typename T >
operator T () { return T(); } // line 23
};


int main()
{
using namespace std;

cout << boolalpha;

#define TEST( X, Y ) \
cout \
<< #X " operator " #Y "() " \
<< has_conversion_operator< X, Y >::bool_value \
<< '\n'

TEST( X, int );

TEST( X, int & ); // line 41
}

TIA.

Rob.
 
V

Victor Bazarov

Rob said:
I have the following code , part of a trait to detect wether a type
has a member operator "Type" (), it works fine with g++ 3.4 (msvc
compiles it but it doesn't work for template'd operator T ()) but
with CBuilderX (EDG frontend) and Comeau's online compiler I get:

test.cpp:23: error invalid type conversion detected during
instantiation of "X::eek:perator T() [with T=int &]" at line 41

I.e it instantiates X::eek:perator< int & > int & () inside the
sizeof, any other compiler than EDG and I'd automaticly think
this was a compiler bug.

Thought's ?

I have hard time understanding your writing, sorry. I am sure it is
not your fault. You just have this unique style of putting together
sentences that escape me. But one thing I think I should mention:
it's impossible to instantiate T() with T == int&. References have to
be initialised. Perhaps that's why you get the error. "invalid type
conversion" may just be bad wording.
#include <iostream>
#include <iomanip>

template < typename T, typename Type >
struct has_conversion_operator
{
private:
template < typename V, Type (V::*M)() > struct empty_t_;
template < typename U >
static char helper_f( empty_t_< U, &U::eek:perator Type > * );
template < typename U >
static char (&helper_f( ... ))[2];

public:
static bool const bool_value =
( sizeof( helper_f< T >( 0 ) ) == sizeof( char ) )
;
};

struct X
{
template < typename T >
operator T () { return T(); } // line 23
};


int main()
{
using namespace std;

cout << boolalpha;

#define TEST( X, Y ) \
cout \
<< #X " operator " #Y "() " \
<< has_conversion_operator< X, Y >::bool_value \
<< '\n'

TEST( X, int );

TEST( X, int & ); // line 41
}

TIA.

Rob.

V
 
R

Rob Williscroft

Victor Bazarov wrote in @newsread1.dllstx09.us.to.verio.net in comp.lang.c++:
I have hard time understanding your writing, sorry. I am sure it is
not your fault. You just have this unique style of putting together
sentences that escape me.

I suspect its me. Just because English is my first language doesn't
mean I'm actually any good at it :).
But one thing I think I should mention:
it's impossible to instantiate T() with T == int&. References have to
be initialised. Perhaps that's why you get the error. "invalid type
conversion" may just be bad wording.

Yes I understand why the member's function body can't be instantiated.

But what I don't understand is why is EDG instantiating it inside
the sizeof expression.

The body of a function should *never* be needed in a compile
time expression (since it can't be used anyway :).

Rob.
 
V

Victor Bazarov

Rob said:
Victor Bazarov wrote in news:5wzdd.5994$Ae.5220


Yes I understand why the member's function body can't be instantiated.

But what I don't understand is why is EDG instantiating it inside
the sizeof expression.

The body of a function should *never* be needed in a compile
time expression (since it can't be used anyway :).

Well, my understanding is that you cannot prohibit instantiations based
on a chance that it can't be used. You cannot really know that it can't
be used until you try to instantiate it, no?

As to sizeof, it's on the edge of my understanding of how templates work
and how instantiation is triggered. More a feeling than understanding,
really. So, I wish I had a good explanation. Have you tried talking
to Comeau folks directly?

V
 
R

Rob Williscroft

Victor Bazarov wrote in @newsread1.dllstx09.us.to.verio.net in comp.lang.c++:
Well, my understanding is that you cannot prohibit instantiations
based on a chance that it can't be used. You cannot really know that
it can't be used until you try to instantiate it, no?

Well there is no chance here (3.2/2, snipped):

An expression is potentially evaluated unless it appears where
an [...] is the operand of the sizeof operator (5.3.3), [...]
An object or non-overloaded function is used if its name appears
in a potentially-evaluated expression.

So the member isn't "used" by sizeof.
As to sizeof, it's on the edge of my understanding of how templates
work and how instantiation is triggered. More a feeling than
understanding, really.

I /think/ I understand it, but 2 EDG frontends disagree with me.
When I find I dissagree with EDG I expect to find I'm wrong.
So, I wish I had a good explanation.

Me too :) but thanks for trying.
Have you tried talking to Comeau folks directly?

No, but I'm not a customer, so it wouldn't be my first option :).

An example that doesn't fail:

#include <iostream>

struct X
{
template < typename T >
T &f( T arg ) { return T(); }
};

int main()
{
std::cout
<< "sizeof( ... ) "
<< sizeof( (int & (X::*)( int ))&X::f )
<< '\n'
;
}

But put the &X::f in as a template argument (as in the original
example) and it fails, so I'm increasingly leaning towards this
being a bug.

Rob.
 
C

Chris Theis

Rob Williscroft said:
I have the following code , part of a trait to detect wether a type
has a member operator "Type" (), it works fine with g++ 3.4 (msvc
compiles it but it doesn't work for template'd operator T ()) but
with CBuilderX (EDG frontend) and Comeau's online compiler I get:

test.cpp:23: error invalid type conversion detected during
instantiation of "X::eek:perator T() [with T=int &]" at line 41

I.e it instantiates X::eek:perator< int & > int & () inside the
sizeof, any other compiler than EDG and I'd automaticly think
this was a compiler bug.

Thought's ?

#include <iostream>
#include <iomanip>

template < typename T, typename Type >
struct has_conversion_operator
{
private:
template < typename V, Type (V::*M)() > struct empty_t_;
template < typename U >
static char helper_f( empty_t_< U, &U::eek:perator Type > * );
template < typename U >
static char (&helper_f( ... ))[2];

public:
static bool const bool_value =
( sizeof( helper_f< T >( 0 ) ) == sizeof( char ) )
;
};

struct X
{
template < typename T >
operator T () { return T(); } // line 23
};


int main()
{
using namespace std;

cout << boolalpha;

#define TEST( X, Y ) \
cout \
<< #X " operator " #Y "() " \
<< has_conversion_operator< X, Y >::bool_value \
<< '\n'

TEST( X, int );

TEST( X, int & ); // line 41
}

TIA.

Interesting thing. Which version of MSVC did you use? I quickly checked with
MSVC 7.1 and it compiles fine, which, judging from the code, it should IMHO.

What comes to my mind regarding the error you get with EDG is that there
might be a problem with the translation phases in combination with
templates. As it seems to me the compiler gets the impression that is has to
produce code to instantiate your template before getting to the part where
sizeof() is treated in a special way.
I would agree with you that this seems to be a bug, but until now I thought
that MSVC is based on the EDG backend and therefore this discrepancy is
surprising.

However, a rather similar approach (slightly modified from an idea by Andrei
Alexandrescu) that I use for testing conversions for classes, compiles fine
with Comeau.

template<class T, class U>
class CConversion {
typedef char Small;
class CBig { char m_Dummy[2]; };
static Small Test(const U& );
static CBig Test(...);
static T MakeT();
public:
enum { bExists = sizeof( Test(MakeT())) == sizeof(Small) };
};

Cheers
Chris
 
T

Tom Widmer

I have the following code , part of a trait to detect wether a type
has a member operator "Type" (), it works fine with g++ 3.4 (msvc
compiles it but it doesn't work for template'd operator T ()) but
with CBuilderX (EDG frontend) and Comeau's online compiler I get:

test.cpp:23: error invalid type conversion detected during
instantiation of "X::eek:perator T() [with T=int &]" at line 41

I.e it instantiates X::eek:perator< int & > int & () inside the
sizeof, any other compiler than EDG and I'd automaticly think
this was a compiler bug.

Thought's ?

Looks like a bug to me too - I concur that the body of operator<int&>
int& should not be instantiated, only the signature.

I imagine Greg Comeau would be interested in a bug report (assuming it
does turn out to be a bug), even if you aren't a customer.

Tom
 
R

Rob Williscroft

Chris Theis wrote in in comp.lang.c++:
Interesting thing. Which version of MSVC did you use? I quickly
checked with MSVC 7.1 and it compiles fine, which, judging from the
code, it should IMHO.

Yes it compiles, but produces incorrect results, when the type being
tested has a template operator T, but works for non template operator's
What comes to my mind regarding the error you get with EDG is that
there might be a problem with the translation phases in combination
with templates. As it seems to me the compiler gets the impression
that is has to produce code to instantiate your template before
getting to the part where sizeof() is treated in a special way.

There is some problem when a member pointer is taken as a template
argument inside a sizeof expression, i.e. its the:

sizeof( empty_t_< U, &U::eek:perator Type > );

part that appears to be the problem.

Test case:

#include <iostream>

struct X
{
template < typename T >
T &f( T arg ) { return T(); }
};

template < typename T, int & (T::*)( int ) > struct empty_t_ {};

int main()
{
std::cout
<< "sizeof( ... ) "
<< sizeof( empty_t_< X, &X::f > )
<< '\n'
;
}

This also fails on msvc 7.1, but works on gcc 3.4.
I would agree with you that this seems to be a bug, but until now I
thought that MSVC is based on the EDG backend and therefore this
discrepancy is surprising.

No, you are maybe thinking of Intel 7.1, Microsoft write there own
frontend AFAICT.
However, a rather similar approach (slightly modified from an idea by
Andrei Alexandrescu) that I use for testing conversions for classes,
compiles fine with Comeau.

Yep, not sure its that similar though, this isn't a full conversion test.

I'm thinking of using it like:

struct X
{
template < typename T >
X(
T const &,
typename disable_if< has_conversion_op< T, X > >::type * = 0
)
{
}
};

So its used to disable a conversion sequence if another one
already exists.

Rob.
 
R

Rob Williscroft

Tom Widmer wrote in in
comp.lang.c++:
Looks like a bug to me too - I concur that the body of operator<int&>
int& should not be instantiated, only the signature.

Ok, thanks.
I imagine Greg Comeau would be interested in a bug report (assuming it
does turn out to be a bug), even if you aren't a customer.

I'll give it a few days to see if I get any further feedback and do that.

Rob.
 
C

Chris Theis

Rob Williscroft said:
Chris Theis wrote in in comp.lang.c++:


Yes it compiles, but produces incorrect results, when the type being
tested has a template operator T, but works for non template operator's


There is some problem when a member pointer is taken as a template
argument inside a sizeof expression, i.e. its the:

sizeof( empty_t_< U, &U::eek:perator Type > );

part that appears to be the problem.

Test case:

#include <iostream>

struct X
{
template < typename T >
T &f( T arg ) { return T(); }
};

template < typename T, int & (T::*)( int ) > struct empty_t_ {};

int main()
{
std::cout
<< "sizeof( ... ) "
<< sizeof( empty_t_< X, &X::f > )
<< '\n'
;
}

This also fails on msvc 7.1, but works on gcc 3.4.


No, you are maybe thinking of Intel 7.1, Microsoft write there own
frontend AFAICT.

Yes, I was mistaken but Intel is based on KAI. However, EDG list Comeau as
end-license users of their frontend.
Yep, not sure its that similar though, this isn't a full conversion test.

I'm thinking of using it like:

struct X
{
template < typename T >
X(
T const &,
typename disable_if< has_conversion_op< T, X > >::type * = 0
)
{
}
};

So its used to disable a conversion sequence if another one
already exists.

It looks as if there is a probleme with pointer to template members
violating the SFINAE rule. There were some probable defect reports for
EDG/Comeau on the boost list some time ago. I guess that the people at
Comeau/EDG might be interested in that problem.

Cheers
Chris
 
T

Tom Widmer

Yes, I was mistaken but Intel is based on KAI. However, EDG list Comeau as
end-license users of their frontend.

EDG is used by:

Kai C++ (deceased)
Intel C++ (which isn't based on Kai C++, even though Intel bought Kai)
Borland C++ BuilderX prototype compiler (not yet formally released?)
Comeau C++
Quite a few embedded C++ compilers

Microsoft have their own front end, as do GNU and Metrowerks.

(About Kai and Intel, from
http://www.pallas.com/e/products/kai-c/special/announcement.htm:
Is the Intel C++ Compiler for Linux an extension of KAI C++, or are
they different products?

The Intel C++ compiler and KAI C++ are different products.

* The Intel C++ compiler has an integrated backend code generator.
KAI C++ uses gcc on Linux for code generation.
* Both the Intel C++ compiler and KAI C++ use compiler frontend
technology from Edison Design Group (EDG).
* Intel C++ and KAI C++ use different technology for the Standard
Template Library (STL).
* Intel C++ will not include the parallel prelinking functionality
provided by KAI C++.
* KAI C++ currently provides a higher level of ISO* compliance
than the Intel C++ compiler for Linux. Intel's goal is for the Intel
C++ compiler for Linux to match KAI C++ ISO compliance in early 2003.)

Tom
 
C

Chris Theis

Tom Widmer said:
EDG is used by:

Kai C++ (deceased)
Intel C++ (which isn't based on Kai C++, even though Intel bought Kai)
Borland C++ BuilderX prototype compiler (not yet formally released?)
Comeau C++
Quite a few embedded C++ compilers

Microsoft have their own front end, as do GNU and Metrowerks.

(About Kai and Intel, from
http://www.pallas.com/e/products/kai-c/special/announcement.htm:
Is the Intel C++ Compiler for Linux an extension of KAI C++, or are
they different products?

The Intel C++ compiler and KAI C++ are different products.

* The Intel C++ compiler has an integrated backend code generator.
KAI C++ uses gcc on Linux for code generation.
* Both the Intel C++ compiler and KAI C++ use compiler frontend
technology from Edison Design Group (EDG).
* Intel C++ and KAI C++ use different technology for the Standard
Template Library (STL).
* Intel C++ will not include the parallel prelinking functionality
provided by KAI C++.
* KAI C++ currently provides a higher level of ISO* compliance
than the Intel C++ compiler for Linux. Intel's goal is for the Intel
C++ compiler for Linux to match KAI C++ ISO compliance in early 2003.)

Tom

Thanks for shedding some light on this issue!

Cheers
Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,516
Latest member
ChrisHibbs

Latest Threads

Top