partial ordering of template functions 
Author Message
 partial ordering of template functions

Is partial ordering of template functions supposed to be working in VC++
.NET? I'm getting some very peculiar results. Have a look at the following
code

#include <iostream>
using namespace std;

class X {};

// swap these lines for bug
template <class T, class U> void operator+(const T& x, const U& y);
template <class T> void operator+(const T& x, const T& y);

template <class T, class U>
void operator+(const T& x, const U& y)
{
cout << "diff\n";

Quote:
}

template <class T>
void operator+(const T& x, const T& y)
{
cout << "same\n";

Quote:
}

int main()
{
X x;
x + 2;
x + x;

Quote:
}

This prints

diff
same

which I think is the right result. However if I swap the two prototypes
above (see comment) I get

diff
diff

Wierd. Perhaps even stranger if I replace operator+ with a regular function
(called func, say) I get the error message

c:\Projects\test\main.cpp(60): error C2667: 'func' : none of 2 overloads
have a best conversion

Other apparently harmless transformations have strange effects, for instance
replacing x + 2 with operator+(x, 2) or replacing const T& with T.

Does anyone else have any experiences with this? As it happens the working
code above is exactly what I want to do but the whole area seems a little
fragile.

Is partial ordering supposed to be working in the current version of VC++
.NET or is it one of the things scheduled for the 2003 release?

Thanks,
John



Sat, 28 May 2005 06:41:30 GMT  
 partial ordering of template functions

Quote:
> Is partial ordering supposed to be working in the current version of VC++
> .NET or is it one of the things scheduled for the 2003 release?

The latter.

-cd



Sat, 28 May 2005 06:43:31 GMT  
 partial ordering of template functions



Quote:


> > Is partial ordering supposed to be working in the current version of
VC++
> > .NET or is it one of the things scheduled for the 2003 release?

> The latter.

> -cd

Thanks for the info but now I'm puzzled how I got a working program using
partial ordering of template functions!

john



Sat, 28 May 2005 06:51:09 GMT  
 partial ordering of template functions

Quote:

> Thanks for the info but now I'm puzzled how I got a working program using
> partial ordering of template functions!

Just lucky I guess :)

I've only ever heard that VC7 doesn't to partial ordering - but perhaps in
fact it implements some of the rules but not all of them?  Just a guess.

-cd



Sat, 28 May 2005 06:56:33 GMT  
 partial ordering of template functions



Quote:


> > Thanks for the info but now I'm puzzled how I got a working program
using
> > partial ordering of template functions!

> Just lucky I guess :)

> I've only ever heard that VC7 doesn't to partial ordering - but perhaps in
> fact it implements some of the rules but not all of them?  Just a guess.

> -cd

VC7 definitely doesn't do any partial ordering, and neither did VC6.

However, in some cases, VC6 would resolve an overload even though it didn't
do partial ordering at all.  We tightened that up in VC7, and some code was
broken because of it.

So if it was working, you were lucky!  Sometimes it might have "worked" but
VC6 might have generated incorrect code.

Jason Shirk
VC++ Compiler Team



Sat, 28 May 2005 07:19:25 GMT  
 partial ordering of template functions

Quote:
> Is partial ordering of template functions supposed to be working in VC++
> .NET? I'm getting some very peculiar results. Have a look at the following
> code

> #include <iostream>
> using namespace std;

> class X {};

> // swap these lines for bug
> template <class T, class U> void operator+(const T& x, const U& y);
> template <class T> void operator+(const T& x, const T& y);

> template <class T, class U>
> void operator+(const T& x, const U& y)
> {
> cout << "diff\n";
> }

> template <class T>
> void operator+(const T& x, const T& y)
> {
> cout << "same\n";
> }

> int main()
> {
> X x;
> x + 2;
> x + x;
> }

> This prints

> diff
> same

> which I think is the right result. However if I swap the two prototypes
> above (see comment) I get

> diff
> diff

> Wierd. Perhaps even stranger if I replace operator+ with a regular function
> (called func, say) I get the error message

> c:\Projects\test\main.cpp(60): error C2667: 'func' : none of 2 overloads
> have a best conversion

> Other apparently harmless transformations have strange effects, for instance
> replacing x + 2 with operator+(x, 2) or replacing const T& with T.

> Does anyone else have any experiences with this? As it happens the working
> code above is exactly what I want to do but the whole area seems a little
> fragile.

> Is partial ordering supposed to be working in the current version of VC++
> .NET or is it one of the things scheduled for the 2003 release?

> Thanks,
> John

hi, John. These guys definitely know more details about the compiler itself
than me. But let's take a logical look at your problem. You have:

template <class T, class U> void operator+(const T& x, const U& y);
template <class T> void operator+(const T& x, const T& y);

Consider the x + 2 statement. It is unwound to:

template <X, int> void operator+(const X& x, const int& y);
template <X> void operator+(const X& x, const X& y);

So definitely the 1st function is better. Now consider x + x:

template <X, X> void operator+(const X& x, const X& y);
template <X> void operator+(const X& x, const X& y);

So as you may see ignoring template signature we have absolutely identical
functions, namely:

void operator+(const X& x, const X& y); //diff
void operator+(const X& x, const X& y); //same

Thus, what should a compiler do? Apparently, take the very last definition
of the function. Therefore, for the case when you have

void operator+(const X& x, const X& y); //same
void operator+(const X& x, const X& y); //diff

diff
diff

is printed. Where does my logic have a flaw?

-d



Sat, 28 May 2005 09:52:21 GMT  
 partial ordering of template functions


Quote:

> > Is partial ordering of template functions supposed to be working in VC++
> > .NET? I'm getting some very peculiar results. Have a look at the
following
> > code

> > #include <iostream>
> > using namespace std;

> > class X {};

> > // swap these lines for bug
> > template <class T, class U> void operator+(const T& x, const U& y);
> > template <class T> void operator+(const T& x, const T& y);

> > template <class T, class U>
> > void operator+(const T& x, const U& y)
> > {
> > cout << "diff\n";
> > }

> > template <class T>
> > void operator+(const T& x, const T& y)
> > {
> > cout << "same\n";
> > }

> > int main()
> > {
> > X x;
> > x + 2;
> > x + x;
> > }

> > This prints

> > diff
> > same

> > which I think is the right result. However if I swap the two prototypes
> > above (see comment) I get

> > diff
> > diff

> > Wierd. Perhaps even stranger if I replace operator+ with a regular
function
> > (called func, say) I get the error message

> > c:\Projects\test\main.cpp(60): error C2667: 'func' : none of 2 overloads
> > have a best conversion

> > Other apparently harmless transformations have strange effects, for
instance
> > replacing x + 2 with operator+(x, 2) or replacing const T& with T.

> > Does anyone else have any experiences with this? As it happens the
working
> > code above is exactly what I want to do but the whole area seems a
little
> > fragile.

> > Is partial ordering supposed to be working in the current version of
VC++
> > .NET or is it one of the things scheduled for the 2003 release?

> > Thanks,
> > John

> hi, John. These guys definitely know more details about the compiler
itself
> than me. But let's take a logical look at your problem. You have:

> template <class T, class U> void operator+(const T& x, const U& y);
> template <class T> void operator+(const T& x, const T& y);

> Consider the x + 2 statement. It is unwound to:

> template <X, int> void operator+(const X& x, const int& y);
> template <X> void operator+(const X& x, const X& y);

> So definitely the 1st function is better. Now consider x + x:

> template <X, X> void operator+(const X& x, const X& y);
> template <X> void operator+(const X& x, const X& y);

> So as you may see ignoring template signature we have absolutely identical
> functions, namely:

> void operator+(const X& x, const X& y); //diff
> void operator+(const X& x, const X& y); //same

> Thus, what should a compiler do? Apparently, take the very last definition
> of the function. Therefore, for the case when you have

> void operator+(const X& x, const X& y); //same
> void operator+(const X& x, const X& y); //diff

> diff
> diff

> is printed. Where does my logic have a flaw?

> -d

Good explanation, it might even be right! Doesn't explain why the compiler
can't manage the same if the operator is a function, or if const T& is
changed to T however.

john



Sun, 29 May 2005 04:51:48 GMT  
 partial ordering of template functions

Quote:



>>>Is partial ordering of template functions supposed to be working in VC++
>>>.NET? I'm getting some very peculiar results. Have a look at the

> following

>>>code

>>>#include <iostream>
>>>using namespace std;

>>>class X {};

>>>// swap these lines for bug
>>>template <class T, class U> void operator+(const T& x, const U& y);
>>>template <class T> void operator+(const T& x, const T& y);

>>>template <class T, class U>
>>>void operator+(const T& x, const U& y)
>>>{
>>>cout << "diff\n";
>>>}

>>>template <class T>
>>>void operator+(const T& x, const T& y)
>>>{
>>>cout << "same\n";
>>>}

>>>int main()
>>>{
>>>X x;
>>>x + 2;
>>>x + x;
>>>}

>>>This prints

>>>diff
>>>same

>>>which I think is the right result. However if I swap the two prototypes
>>>above (see comment) I get

>>>diff
>>>diff

>>>Wierd. Perhaps even stranger if I replace operator+ with a regular

> function

>>>(called func, say) I get the error message

>>>c:\Projects\test\main.cpp(60): error C2667: 'func' : none of 2 overloads
>>>have a best conversion

>>>Other apparently harmless transformations have strange effects, for

> instance

>>>replacing x + 2 with operator+(x, 2) or replacing const T& with T.

>>>Does anyone else have any experiences with this? As it happens the

> working

>>>code above is exactly what I want to do but the whole area seems a

> little

>>>fragile.

>>>Is partial ordering supposed to be working in the current version of

> VC++

>>>.NET or is it one of the things scheduled for the 2003 release?

>>>Thanks,
>>>John

>>hi, John. These guys definitely know more details about the compiler

> itself

>>than me. But let's take a logical look at your problem. You have:

>>template <class T, class U> void operator+(const T& x, const U& y);
>>template <class T> void operator+(const T& x, const T& y);

>>Consider the x + 2 statement. It is unwound to:

>>template <X, int> void operator+(const X& x, const int& y);
>>template <X> void operator+(const X& x, const X& y);

>>So definitely the 1st function is better. Now consider x + x:

>>template <X, X> void operator+(const X& x, const X& y);
>>template <X> void operator+(const X& x, const X& y);

>>So as you may see ignoring template signature we have absolutely identical
>>functions, namely:

>>void operator+(const X& x, const X& y); //diff
>>void operator+(const X& x, const X& y); //same

>>Thus, what should a compiler do? Apparently, take the very last definition
>>of the function. Therefore, for the case when you have

>>void operator+(const X& x, const X& y); //same
>>void operator+(const X& x, const X& y); //diff

>>diff
>>diff

>>is printed. Where does my logic have a flaw?

>>-d

> Good explanation, it might even be right! Doesn't explain why the compiler
> can't manage the same if the operator is a function, or if const T& is
> changed to T however.

> john

Okay, so for this code:

template <class T> void foo(const T& x, const T& y);
template <class T, class U> void foo(const T& x, const U& y);

template <class T>
void foo(const T& x, const T& y)
{
cout << "same\n";

Quote:
}

template <class T, class U>
void foo(const T& x, const U& y)
{
cout << "diff\n";

Quote:
}

int main()
{
X x;
foo(x, 2); //line #48
foo(x, x); //line #49

Quote:
}

you might be having (at least I do):

1.cpp(49) : error C2667: 'foo' : none of 2 overloads have a best conversion
         1.cpp(26): could be 'void foo(const T &,const U &)'
         1.cpp(24): or       'void foo(const T &,const T &)'
         while trying to match the argument list '(X, X)'
1.cpp(49) : error C2668: 'foo' : ambiguous call to overloaded function
         1.cpp(26): could be 'void foo(const T &,const U &)'
         1.cpp(24): or       'void foo(const T &,const T &)'
         while trying to match the argument list '(X, X)'

No questions about $48, right? What unwinding we have again:

template <class T = X> void foo(const X& x, const X& y);
template <class T = X, class U = X> void foo(const X& x, const X& y);

so how to resolve an ambiguity if we have two identical signatures? No way!
For whatever you want to change arguments, it will not work:

template <class T = X> void foo(const X x, const X &y);
template <class T = X, class U = X> void foo(const X &x, const X y);

What is the difference actually? Indeed, no matter what are the arguments,
either const T x, or const T& x, or X x, or X& x, it makes difference -
ambiguity still exists though with some additional problems like operator =.

-d



Sun, 29 May 2005 15:54:15 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Partial specialization of a member function of class template

2. Partial template specialization problem?

3. Template specialization problem (not partial-specialization)

4. Release plan for partial template specialization?

5. Partial Template Specialization?

6. Partial template specialization??

7. partial template specialization

8. partial template specialization

9. Partial template class specialization.

10. VC++6.0 partial template specialization?

11. Partial specialization of Template

12. Partial template specialization

 

 
Powered by phpBB® Forum Software