overload resolution / integral promotion / standard

A

Alexander Stippler

Hi,

I have got a question concerning the overload resolution rules of C++ and
enumeration types. The following little test program illustrates the
situation:

enum { red, green, blue };


template <class A, class B>
A
operator+(const A &a, const B& b)
{
return a;
}


int
main()
{
int i = 0;
i = i + green;

return 0;
}


The code does not really make much sense, but illustrates my problem: I
would never have guessed that every compiler I tried uses the template
operator+ instead of a builtin +.
IMO the compiler has to prefer the builtin + according to the standard:

1) both the user-defined + and the builtin + are in the candidate set.
[13.3.1/13.3.2] and [13.6.2/13.6.12].
2) both are viable.
3) but the built-in + is better [13.3.3].

By the way, I have neglected the fact, that the enum is an unnamed type, so
that the compiler should not choose the template version anyway (or should
it?)

Are my considerations wrong or the compilers (gcc3.3, como4.3, icc7.01)?

regards,
alex
 
R

Rob Williscroft

Alexander Stippler wrote in
Hi,

I have got a question concerning the overload resolution rules of C++
and enumeration types. The following little test program illustrates
the situation:

enum { red, green, blue };


template <class A, class B>
A
operator+(const A &a, const B& b)
{
return a;
}


int
main()
{
int i = 0;
i = i + green;

return 0;
}


The code does not really make much sense, but illustrates my problem:
I would never have guessed that every compiler I tried uses the
template
operator+ instead of a builtin +.
IMO the compiler has to prefer the builtin + according to the
standard:

1) both the user-defined + and the builtin + are in the candidate set.
[13.3.1/13.3.2] and [13.6.2/13.6.12].
2) both are viable.
3) but the built-in + is better [13.3.3].

Well the builtin requires an extra conversion enum to int. Note that
argument conversion sequences are considered before other rules,
for instance the "prefere non-template over template" rule.
By the way, I have neglected the fact, that the enum is an unnamed
type, so that the compiler should not choose the template version
anyway (or should it?)

I've read this argument before, though I've never read of a compiler
that actually doesn't treat unnamed enum's as though they have a
type-name.

Ok just found one:

enum { red, green, blue };

template <class A, class B>
A operator+(const A &a, const B& b)
{
return a;
}

struct Dumby {};

Dumby operator + ( Dumby const &, int );

int main()
{
Dumby i;
i = i + green;

return 0;
}

"sourceFile.cpp", line 17: error:
a template argument may not reference an unnamed type
i = i + green;
^
The compiler is at http://www.dinkumware.com/exam/dinkumExam.aspx

It gives:

"sourceFile.cpp", line 13: error:
identifier "green" is undefined
i = i + green;
^

for your original code.

I don't know what EDG version this is. So I've now idea if its more
recient than the como compiler you tried.

Clearly the compiler doesn't consider SFINAE to apply, I would
hazard a guess that this is an illegal substitution not a
"Substitution Failure", hence it doesn't select the builtin op +
anyway.

Rob.
 
R

Rob Williscroft

Rolf Magnus wrote in
Why should there be any difference between a named and an unnamed enum
type?

IIUC because it needs a name with external linkage to base the
external-linkage name it's going to give to the instantiated
operator + < A, <unnamed-type> >( A const &, <unnamed-type> const &).

Rob.
 
A

Alexander Stippler

Rob Williscroft wrote:

Well the builtin requires an extra conversion enum to int. Note that
argument conversion sequences are considered before other rules,
for instance the "prefere non-template over template" rule.

Your completely right here.
Well,
the standard says: "If a substitution in a template parameter or in the
function type of the function template results in an invalid type, type
deduction fails." A unnamed type is and invalid type, so what?
como emits the error message:
"a template argument may not reference an unnamed type"
So it notices that it is an unnamed type, but it doesn't treat it as invalid
type in template argument deduction. Would it not have to?
intel C++ and gcc choose the template version anyway.

regards,
alex
 
T

tom_usenet

Well,
the standard says: "If a substitution in a template parameter or in the
function type of the function template results in an invalid type, type
deduction fails." A unnamed type is and invalid type, so what?
como emits the error message:
"a template argument may not reference an unnamed type"
So it notices that it is an unnamed type, but it doesn't treat it as invalid
type in template argument deduction. Would it not have to?
intel C++ and gcc choose the template version anyway.

The list of substitutions that cause type deduction to fail are listed
in 14.8.2/2. This one isn't mentioned (using a non-extern type), so
14.8.2/5 applies and I assume it should give an error (as EDG does).

Tom
 
A

Alexander Stippler

tom_usenet said:
The list of substitutions that cause type deduction to fail are listed
in 14.8.2/2. This one isn't mentioned (using a non-extern type), so
14.8.2/5 applies and I assume it should give an error (as EDG does).

Tom

I think the standard is not very precise here. IMO a compiler should not
consider a template function in the given context, since it would have to
instantiate it with an unnamed type, what is not allowed. And the standard
says:

"Template arguments can be deduced in several different contexts, but in
each case a type that is specified in terms of template parameters(call it
P) is compared with an actual type (call it A). and an attempt is made to
find template argument values ( ... ) that will make P, after substitution
of the deduced values (call it the deduced A), compatible with A.
[14.8.2.4] IMO a compiler should therefore not try any unnamed type as
template parameter anyway in this process, since this does not make sense -
they are not allowed. So why try them?
To me - independent of what the standard says - it would make sense to
handle it the way I proposed. What do you think?

regards,
alex
 
R

Rolf Magnus

Alexander said:
Hi,

I have got a question concerning the overload resolution rules of C++
and enumeration types. The following little test program illustrates
the situation:

enum { red, green, blue };


template <class A, class B>
A
operator+(const A &a, const B& b)
{
return a;
}


int
main()
{
int i = 0;
i = i + green;

return 0;
}


The code does not really make much sense, but illustrates my problem:
I would never have guessed that every compiler I tried uses the
template operator+ instead of a builtin +.

You can overload operators for enum types just the same as for classes
(13.5p6), so your overloaded template operator gets called for it.
IMO the compiler has to prefer the builtin + according to the
standard:

1) both the user-defined + and the builtin + are in the candidate set.
[13.3.1/13.3.2] and [13.6.2/13.6.12].
2) both are viable.
3) but the built-in + is better [13.3.3].

By the way, I have neglected the fact, that the enum is an unnamed
type, so that the compiler should not choose the template version
anyway (or should it?)

Why should there be any difference between a named and an unnamed enum
type?
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top