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 9 2736
Alexander Stippler wrote: 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?
Alexander Stippler wrote in news:3f******@n ews.uni-ulm.de: 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+(cons t 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
"Substituti on Failure", hence it doesn't select the builtin op +
anyway.
Rob.
-- http://www.victim-prime.dsl.pipex.com/
Rolf Magnus wrote in news:bn******** *****@news.t-online.com: 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?
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.
-- http://www.victim-prime.dsl.pipex.com/
Rob Williscroft wrote: enum { red, green, blue };
template <class A, class B> A operator+(con st A &a, const B& b) { return a; }
int main() { int i = 0; i = i + green;
return 0; }
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
On Wed, 29 Oct 2003 13:58:37 +0100, Alexander Stippler
<st**@mathemati k.uni-ulm.de> wrote: 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
tom_usenet wrote: On Wed, 29 Oct 2003 13:58:37 +0100, Alexander Stippler <st**@mathemati k.uni-ulm.de> wrote:
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
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
Alexander Stippler wrote in news:3f******@n ews.uni-ulm.de: 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.
In the first quote above I read "..substitu tion ... results in an
invalid type ..." not "...substitutio n ... *of* ... invalid type ...".
Hence IIUC como is right here.
enum { unnamed };
template < int i > int value() { return i; }
int main() { value< unnamed >(); }
The above is Ok as substitution doesent result in an invalid type.
(I mention this as it appears to be a case where you can use an
anonymous enum with templates - I wasn't sure it was possible :).
Where as this:
template < typename T > stuct name {};
template < typename T> name< T > named( T const &v )
{
return name< T >();
}
does, the invalid type being name< hasnt-got-a-type-name >. But it
will never get this far as the substitution T = hasnt-got-a-type-name
is illegal, as T must be a type-name with external linkage. "unnamed"
above has neither of these (a type-name or external linkage).
Thanks for bring this up BTW. I'd read something about problems with
anonymous enum's, but it was a aside in a post about something else
so I never really got it till now. Since then I've been happlesly
coding enum give_it_a_name { Whatever }; just-in-case, without
understanding why :).
Rob.
-- http://www.victim-prime.dsl.pipex.com/
On Wed, 29 Oct 2003 16:10:45 +0100, Alexander Stippler
<st**@mathemati k.uni-ulm.de> wrote: 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.
The parameter types are legal types though, it is only the template
instantiation that is illegal. The validity of the instantiation isn't
checked until later.
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?
There is a decent thread about this stuff here: http://groups.google.co.uk/groups?hl...50c%40c161550a
Tom
tom_usenet wrote: The parameter types are legal types though, it is only the template instantiation that is illegal. The validity of the instantiation isn't checked until later.
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? There is a decent thread about this stuff here:
http://groups.google.co.uk/groups?hl...50c%40c161550a Tom
I'm afraid, you're right in terms of the standard. But considering 'normal
human logic', why does it make sense for a compiler to instantiate template
parameters with unnamed types during overload resolution, knowing exactly
that this can never result in valid code? In other words: If there are
alternatives to such a candidate function, why does it make sense that a
compiler quits the compilation process with an error message, if it would
only have had to ignore some (not instatiatable) candidate, what would btw
decrease compile time a bit, too?
regards,
alex This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: David Sachs |
last post by:
The following program illustrates an interesting effect of the way C++
resolves function overloading.
I have verified with a member of the C++ stardard committee that the output
shown is correct.
*********************************Program********************************
#include <iostream>
using std::cout;
|
by: Niels Dekker (no reply address) |
last post by:
Is it possible for a standard compliant C++ compiler to have
( sizeof(short) < sizeof(int) )
and
( sizeof(short) == sizeof((short)0 + (short)0) )
?
Regards,
Niels Dekker
http://www.xs4all.nl/~nd/dekkerware
|
by: Fred Ma |
last post by:
Hello,
I've been trying to clear up a confusion about
integer promotions during expression evaluation.
I've checked the C FAQ and C++ FAQ (they are
different languages, but I was hoping one would
clear up the confusion), as well as googling
groups and the web.
The confusion is that for a binary operator,
|
by: Carsten Hansen |
last post by:
Suppose I'm using an implementation where an int is 16 bits.
In the program below, what function is called in the first case,
and what is called in the second case?
Also, if there is a difference between C89 and C99, I would
like to know.
I have tried with different compilers, and I see some differences.
Before I file a bug report with my C...
|
by: TTroy |
last post by:
Hello, I'm relatively new to C and have gone through more than 4 books
on it. None mentioned anything about integral promotion, arithmetic
conversion, value preserving and unsigned preserving. And K&R2
mentions "signed extension" everywhere.
Reading some old clc posts, I've beginning to realize that these books
are over-generalizing the...
| |
by: sri |
last post by:
class Base
{
public:
virtual void f(int) { std::cout<<"base.f(int)\n";};
virtual void f(std::complex<double>) { std::cout<<"derived.f
\n"; };
};
class Derived : public Base
{
|
by: Thurston Manson |
last post by:
Suppose I'm using an implementation where an int is 16 bits. In the
program below, what function is called in the first case, and what is
called in the second case? Also, if there is a difference between C89
and C99, I would like to know. I have tried with different compilers,
and I see some differences. Before I file a bug report with my...
|
by: xtrigger303 |
last post by:
Hi to all,
I was reading Mr. Alexandrescu's mojo article and I've a hard time
understanding the following.
Let's suppose I have:
//code
struct A {};
struct B : A {};
|
by: jknupp |
last post by:
In the following program, if the call to bar does not specify the type
as <int>, gcc gives the error "no matching function for call to
‘bar(A&, <unresolved overloaded function type>)’". Since bar
explicitly takes a pointer-to-member with no parameters, why is the
lookup for the overloaded function not able to use the number of
arguments to...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it. ...
| |
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...
| |