template <class X, class T> void method (double u, T v);
template <class X> void method (double u, long v);
...
double u; long v;
Is the following call unambigous (w.r.t. C++ standard)?
method<A> (u, v);
For those wanting to see the true source (chances are that I omitted some important circumstance), this technique is used in new implementation of saturated integer arithmetic for Octave (http://hg.savannah.gnu.org/hgweb/octave/file/c1bada868690/liboctave/ oct-inttypes.h, *.cc) for the octave_int_cmp_op::mop method. gcc 4.x, Intel C++ and Visual C++ seem to accept the code, but a user just reported Cygwin's gcc 3.4.4 failing. I just want to make user I was not unintentionally some common extension. I inspected the C++ draft standard for the rules, and it seems that the answer is yes, because the second declaration is a better match, but I'm still not entirely sure.
> template <class X, class T> void method (double u, T v);
> template <class X> void method (double u, long v);
> ...
> double u; long v;
> Is the following call unambigous (w.r.t. C++ standard)?
> method<A> (u, v);
> For those wanting to see the true source (chances are that I omitted > some important circumstance), > this technique is used in new implementation of saturated integer > arithmetic for Octave > (http://hg.savannah.gnu.org/hgweb/octave/file/c1bada868690/liboctave/ > oct-inttypes.h, *.cc) > for the octave_int_cmp_op::mop method. > gcc 4.x, Intel C++ and Visual C++ seem to accept the code, but a user > just reported Cygwin's gcc 3.4.4 failing. I just want to make user I > was not unintentionally some common extension. I inspected the C++ > draft standard for the rules, and it seems that the answer is yes, > because the second declaration is a better match, but I'm still not > entirely sure.
I think it's a legal overload and there should be no ambiguous call. But overloading/specialization in function templates can be tricky.
"highegg" <high...@gmail.com> wrote: > I inspected the C++ > draft standard for the rules, and it seems that the answer is yes, > because the second declaration is a better match, but I'm still not > entirely sure.
Comeau's C++ compiler (which being based on the EDG front-end is the most standards compliant compiler available to the public) has no issue with the code in strict mode (besides the warnings given, which are due to how I forumulated your question). Since IIRC ambigious calls make a program ill-formed, any extention that accepts it would need to give a warning in a strictly complient compiler. Since Comeau gives no such warning, and ios being run in its strictest mode, I'm reasonably confident that your assesment that the second is a better match is correct. Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2 Copyright 1988-2008 Comeau Computing. All rights reserved. MODE:strict errors C++ noC++0x_extensions
"ComeauTest.c", line 12: warning: variable "u" is used before its value is set method<A> (u, v); ^
"ComeauTest.c", line 12: warning: variable "v" is used before its value is set method<A> (u, v);
Victor Bazarov wrote: > highegg wrote: >> given the declarations >> class A {};
>> template <class X, class T> void method (double u, T v);
>> template <class X> void method (double u, long v);
>> ...
>> double u; long v;
>> Is the following call unambigous (w.r.t. C++ standard)?
>> method<A> (u, v);
>> [..]
> Yes.
I meant to say it was ambiguous. If you know what part of the Draft says the second is a better match, could you point to it, please?
From what I figure, the first template could be more specialised than the second because it has two types defined, not just one. However, all the examples given in the Standard have to do with A<T*> vs A<T> (which makes the former more specialised) and not A<T,U> vs A<T>. My understanding of what makes templates "more specialised" can be incorrect, so I'd appreciated somebody's explanation.
> Since it can be either
> method<A,long>(u, v); // 'X'==A, 'T' is deduced from 'v'
> or
> method<A>(u, v); // 'X'==A, single template argument
> , the compiler can't decide which one you want. If you specify the type > explicitly, like this
> method<A,long>(u, v);
> the ambiguity goes away since it cannot be the second template.
> V
V -- Please remove capital 'A's when replying by e-mail I do not respond to top-posted replies, please don't ask
Victor Bazarov wrote: > Victor Bazarov wrote: > > highegg wrote: > >> given the declarations > >> class A {};
> >> template <class X, class T> void method (double u, T v);
> >> template <class X> void method (double u, long v);
> >> ...
> >> double u; long v;
> >> Is the following call unambigous (w.r.t. C++ standard)?
> >> method<A> (u, v);
> >> [..]
> > Yes.
> I meant to say it was ambiguous. If you know what part of the Draft > says the second is a better match, could you point to it, please?
> From what I figure, the first template could be more specialised than > the second because it has two types defined, not just one. However, all > the examples given in the Standard have to do with A<T*> vs A<T> (which > makes the former more specialised) and not A<T,U> vs A<T>. My > understanding of what makes templates "more specialised" can be > incorrect, so I'd appreciated somebody's explanation.
[...]
The second "method" isn't a specialization; it's an overload. The only specialization for function templates is total specialization, that is, a specialization with all types specified.
One can get the equivalent of partial specialization by using a helper class:
template<class X,class T> struct method_ { static void f( double u, T v ); };
// partial specialization template<class X> struct method_<X,long> { static void f( double u, long v ); };
template <class X, class T> inline void method (double u, T v) { method_<X,T>::f( u, v ); }
> Victor Bazarov wrote: > > highegg wrote: > >> given the declarations > >> class A {};
> >> template <class X, class T> void method (double u, T v);
> >> template <class X> void method (double u, long v);
> >> ...
> >> double u; long v;
> >> Is the following call unambigous (w.r.t. C++ standard)?
> >> method<A> (u, v);
> >> [..]
> > Yes.
> I meant to say it was ambiguous. If you know what part of the Draft > says the second is a better match, could you point to it, please?
> From what I figure, the first template could be more specialised than > the second because it has two types defined, not just one. However, all > the examples given in the Standard have to do with A<T*> vs A<T> (which > makes the former more specialised) and not A<T,U> vs A<T>. My > understanding of what makes templates "more specialised" can be > incorrect, so I'd appreciated somebody's explanation.
> Victor Bazarov wrote: > > highegg wrote: > >> given the declarations > >> class A {};
> >> template <class X, class T> void method (double u, T v);
> >> template <class X> void method (double u, long v);
> >> ...
> >> double u; long v;
> >> Is the following call unambigous (w.r.t. C++ standard)?
> >> method<A> (u, v);
> >> [..]
> > Yes.
> I meant to say it was ambiguous. If you know what part of the Draft > says the second is a better match, could you point to it, please?
> From what I figure, the first template could be more specialised than > the second because it has two types defined, not just one. However, all > the examples given in the Standard have to do with A<T*> vs A<T> (which > makes the former more specialised) and not A<T,U> vs A<T>. My > understanding of what makes templates "more specialised" can be > incorrect, so I'd appreciated somebody's explanation.
Hi Victor,
after reading the relevant sections thoroughly, I think it is the partial template ordering rules in 14.5.5.2 that account for the unambigous resolution. See the paragraphs 2-5. Simply said, the reasoning is that the second template's prototype can be matched by the first, but not vice versa (note the wording in paragraph 3 saying that a *unique* type is synthesized for each type template parameter, i.e. for T in this case). Therefore, the second template is more specialized and will be preferred.
If anyone thinks I'm wrong with this reasoning, please clarify. Anyway, thanks to everyone who replied, especially Joe pointing me to Comeau C++.
highegg wrote: > On 12 Pro, 19:42, Victor Bazarov <v.Abaza...@comAcast.net> wrote: >> Victor Bazarov wrote: >>> highegg wrote: >>>> given the declarations >>>> class A {}; >>>> template <class X, class T> void method (double u, T v); >>>> template <class X> void method (double u, long v); >>>> ... >>>> double u; long v; >>>> Is the following call unambigous (w.r.t. C++ standard)? >>>> method<A> (u, v); >>>> [..] >>> Yes. >> I meant to say it was ambiguous. If you know what part of the Draft >> says the second is a better match, could you point to it, please?
>> From what I figure, the first template could be more specialised than >> the second because it has two types defined, not just one. However, all >> the examples given in the Standard have to do with A<T*> vs A<T> (which >> makes the former more specialised) and not A<T,U> vs A<T>. My >> understanding of what makes templates "more specialised" can be >> incorrect, so I'd appreciated somebody's explanation.
> Hi Victor,
> after reading the relevant sections thoroughly, I think it is the > partial template ordering rules in 14.5.5.2 that account for the > unambigous resolution. See the paragraphs 2-5. > Simply said, the reasoning is that the second template's prototype can > be matched by the first, but not vice versa (note the wording in > paragraph 3 saying that a *unique* type is synthesized for each type > template parameter, i.e. for T in this case). > Therefore, the second template is more specialized and will be > preferred.
> If anyone thinks I'm wrong with this reasoning, please clarify. > Anyway, thanks to everyone who replied, especially Joe pointing me to > Comeau C++.
> Jaroslav Hajek
Thanks, Jaroslav. I take it you meant 14.5.6.2 (not .5.2). I can't find that reasoning you talk about (yes, I have read paragraphs 2-5 in the [temp.func.order] section). Can you please lay your deductions down so that my feeble brain can understand them? Apparently, somewhere in the paragraph 3's first sentence I get lost. How does that sentence explain that in your example the second template is more specialised? Much appreciated!
V -- Please remove capital 'A's when replying by e-mail I do not respond to top-posted replies, please don't ask
> highegg wrote: > > On 12 Pro, 19:42, Victor Bazarov <v.Abaza...@comAcast.net> wrote: > >> Victor Bazarov wrote: > >>> highegg wrote: > >>>> given the declarations > >>>> class A {}; > >>>> template <class X, class T> void method (double u, T v); > >>>> template <class X> void method (double u, long v); > >>>> ... > >>>> double u; long v; > >>>> Is the following call unambigous (w.r.t. C++ standard)? > >>>> method<A> (u, v); > >>>> [..] > >>> Yes. > >> I meant to say it was ambiguous. If you know what part of the Draft > >> says the second is a better match, could you point to it, please?
> >> From what I figure, the first template could be more specialised than > >> the second because it has two types defined, not just one. However, all > >> the examples given in the Standard have to do with A<T*> vs A<T> (which > >> makes the former more specialised) and not A<T,U> vs A<T>. My > >> understanding of what makes templates "more specialised" can be > >> incorrect, so I'd appreciated somebody's explanation.
> > Hi Victor,
> > after reading the relevant sections thoroughly, I think it is the > > partial template ordering rules in 14.5.5.2 that account for the > > unambigous resolution. See the paragraphs 2-5. > > Simply said, the reasoning is that the second template's prototype can > > be matched by the first, but not vice versa (note the wording in > > paragraph 3 saying that a *unique* type is synthesized for each type > > template parameter, i.e. for T in this case). > > Therefore, the second template is more specialized and will be > > preferred.
> > If anyone thinks I'm wrong with this reasoning, please clarify. > > Anyway, thanks to everyone who replied, especially Joe pointing me to > > Comeau C++.
> > Jaroslav Hajek
> Thanks, Jaroslav. I take it you meant 14.5.6.2 (not .5.2). I can't > find that reasoning you talk about (yes, I have read paragraphs 2-5 in > the [temp.func.order] section). Can you please lay your deductions down > so that my feeble brain can understand them? Apparently, somewhere in > the paragraph 3's first sentence I get lost. How does that sentence > explain that in your example the second template is more specialised? > Much appreciated!
Sorry. I was referring to the 1998 standard. Anyway, I'm attaching the relevant text:
2. Given two overloaded function templates, whether one is more specialized than another can be determined by transforming each template in turn and using argument deduction (14.8.2) to compare it to the other. 3. The transformation used is: -- For each type template parameter, synthesize a unique type and substitute that for each occurrence of that parameter in the function parameter list, or for a template conversion function, in the return type. -- For each non-type template parameter... (not relevant) -- For each template template parameter...
4. Using the transformed function parameter list, perform argument deduction against the other function template. The transformed template is at least as specialized as the other if, and only if, the deduction succeeds and the deduced parameter types are an exact match (so the deduction does not rely on implicit conversions).
5. A template is more specialized than another if, and only if, it is at least as specialized as the other template and that template is not at least as specialized as the first.
So, now we're given our pair of declarations
template <class X, class T> void method (double u, T v);
template <class X> void method (double u, long v);
Let's check whether the first is more specialized than the second. For each type template parameter, we synthesize a *unique* type, i.e. we declare: class XX {}; class TT {}; and try matching the prototype method<XX> (double, TT); against the second template - it fails.
Now do it the other way around, and match method<XX> (double, long) against the first template - it succeeds and it is an exact match (T = long).
Therefore, by paragraph 4, the second template is at least as specialized as the first, and because the converse does not hold, the inequality is strict by paragraph 5.
At least, this is my understanding. Comments are welcome.
highegg wrote: > On 15 Pro, 14:48, Victor Bazarov <v.Abaza...@comAcast.net> wrote: >> highegg wrote: >>> On 12 Pro, 19:42, Victor Bazarov <v.Abaza...@comAcast.net> wrote: >>>> Victor Bazarov wrote: >>>>> highegg wrote: >>>>>> given the declarations >>>>>> class A {}; >>>>>> template <class X, class T> void method (double u, T v); >>>>>> template <class X> void method (double u, long v); >>>>>> ... >>>>>> double u; long v; >>>>>> Is the following call unambigous (w.r.t. C++ standard)? >>>>>> method<A> (u, v); >>>>>> [..] >>>>> Yes. >>>> I meant to say it was ambiguous. If you know what part of the Draft >>>> says the second is a better match, could you point to it, please? >>>> From what I figure, the first template could be more specialised than >>>> the second because it has two types defined, not just one. However, all >>>> the examples given in the Standard have to do with A<T*> vs A<T> (which >>>> makes the former more specialised) and not A<T,U> vs A<T>. My >>>> understanding of what makes templates "more specialised" can be >>>> incorrect, so I'd appreciated somebody's explanation. >>> Hi Victor, >>> after reading the relevant sections thoroughly, I think it is the >>> partial template ordering rules in 14.5.5.2 that account for the >>> unambigous resolution. See the paragraphs 2-5. >>> Simply said, the reasoning is that the second template's prototype can >>> be matched by the first, but not vice versa (note the wording in >>> paragraph 3 saying that a *unique* type is synthesized for each type >>> template parameter, i.e. for T in this case). >>> Therefore, the second template is more specialized and will be >>> preferred. >>> If anyone thinks I'm wrong with this reasoning, please clarify. >>> Anyway, thanks to everyone who replied, especially Joe pointing me to >>> Comeau C++. >>> Jaroslav Hajek >> Thanks, Jaroslav. I take it you meant 14.5.6.2 (not .5.2). I can't >> find that reasoning you talk about (yes, I have read paragraphs 2-5 in >> the [temp.func.order] section). Can you please lay your deductions down >> so that my feeble brain can understand them? Apparently, somewhere in >> the paragraph 3's first sentence I get lost. How does that sentence >> explain that in your example the second template is more specialised? >> Much appreciated!
> Sorry. I was referring to the 1998 standard.
Don't apologise, I was looking in the latest draft. My fault.
> 2. Given two overloaded function templates, whether one is more > specialized than another can be determined by transforming each > template in turn and using argument deduction (14.8.2) to compare it > to the other. > 3. The transformation used is: > -- For each type template parameter, synthesize a unique type and > substitute that for each occurrence of that parameter in the function > parameter list, or for a template conversion function, in the return > type. > -- For each non-type template parameter... (not relevant) > -- For each template template parameter...
> 4. Using the transformed function parameter list, perform argument > deduction against the other function template. The transformed > template is at least as specialized as the other if, and only if, the > deduction succeeds and the deduced parameter types are an exact match > (so the deduction does not rely on implicit conversions).
> 5. A template is more specialized than another if, and only if, it is > at least as specialized as the other template and that template is not > at least as specialized as the first.
> So, now we're given our pair of declarations
> template <class X, class T> void method (double u, T v);
> template <class X> void method (double u, long v);
> Let's check whether the first is more specialized than the second. > For each type template parameter, we synthesize a *unique* type, i.e. > we declare: > class XX {}; class TT {}; > and try matching the prototype > method<XX> (double, TT); > against the second template - it fails.
That's where I don't see it, I guess. You're saying "it fails" because the second one cannot be used since TT has no conversion to 'long', is that it?
> Now do it the other way around, and match > method<XX> (double, long) > against the first template - it succeeds and it is an exact match (T = > long).
OK, so the deduction succeeds means that the second is at least as specialised as the first. And since before the first failed, it can't be as specialised as the second, that means the second is more specialised. Did I get that right?
> Therefore, by paragraph 4, the second template is at least as > specialized as the first, and because the converse does not hold, the > inequality is strict by paragraph 5.
> At least, this is my understanding. Comments are welcome.
Sounds reasonable. Thank you again for the explanation!
V -- Please remove capital 'A's when replying by e-mail I do not respond to top-posted replies, please don't ask
> highegg wrote: > > On 15 Pro, 14:48, Victor Bazarov <v.Abaza...@comAcast.net> wrote: > >> highegg wrote: > >>> On 12 Pro, 19:42, Victor Bazarov <v.Abaza...@comAcast.net> wrote: > >>>> Victor Bazarov wrote: > >>>>> highegg wrote: > >>>>>> given the declarations > >>>>>> class A {}; > >>>>>> template <class X, class T> void method (double u, T v); > >>>>>> template <class X> void method (double u, long v); > >>>>>> ... > >>>>>> double u; long v; > >>>>>> Is the following call unambigous (w.r.t. C++ standard)? > >>>>>> method<A> (u, v); > >>>>>> [..] > >>>>> Yes. > >>>> I meant to say it was ambiguous. If you know what part of the Draft > >>>> says the second is a better match, could you point to it, please? > >>>> From what I figure, the first template could be more specialised than > >>>> the second because it has two types defined, not just one. However, all > >>>> the examples given in the Standard have to do with A<T*> vs A<T> (which > >>>> makes the former more specialised) and not A<T,U> vs A<T>. My > >>>> understanding of what makes templates "more specialised" can be > >>>> incorrect, so I'd appreciated somebody's explanation. > >>> Hi Victor, > >>> after reading the relevant sections thoroughly, I think it is the > >>> partial template ordering rules in 14.5.5.2 that account for the > >>> unambigous resolution. See the paragraphs 2-5. > >>> Simply said, the reasoning is that the second template's prototype can > >>> be matched by the first, but not vice versa (note the wording in > >>> paragraph 3 saying that a *unique* type is synthesized for each type > >>> template parameter, i.e. for T in this case). > >>> Therefore, the second template is more specialized and will be > >>> preferred. > >>> If anyone thinks I'm wrong with this reasoning, please clarify. > >>> Anyway, thanks to everyone who replied, especially Joe pointing me to > >>> Comeau C++. > >>> Jaroslav Hajek > >> Thanks, Jaroslav. I take it you meant 14.5.6.2 (not .5.2). I can't > >> find that reasoning you talk about (yes, I have read paragraphs 2-5 in > >> the [temp.func.order] section). Can you please lay your deductions down > >> so that my feeble brain can understand them? Apparently, somewhere in > >> the paragraph 3's first sentence I get lost. How does that sentence > >> explain that in your example the second template is more specialised? > >> Much appreciated!
I think the expression "more specialized" can be confusing in the standard wording. Nevertheless, here's why I think there should be no ambiguous call.
> Don't apologise, I was looking in the latest draft. My fault.
> > Anyway, I'm attaching the
> > relevant text:
> > 2. Given two overloaded function templates, whether one is more > > specialized than another can be determined by transforming each > > template in turn and using argument deduction (14.8.2) to compare it > > to the other. > > 3. The transformation used is: > > -- For each type template parameter, synthesize a unique type and > > substitute that for each occurrence of that parameter in the function > > parameter list, or for a template conversion function, in the return > > type. > > -- For each non-type template parameter... (not relevant) > > -- For each template template parameter...
> > 4. Using the transformed function parameter list, perform argument > > deduction against the other function template. The transformed > > template is at least as specialized as the other if, and only if, the > > deduction succeeds and the deduced parameter types are an exact match > > (so the deduction does not rely on implicit conversions).
> > 5. A template is more specialized than another if, and only if, it is > > at least as specialized as the other template and that template is not > > at least as specialized as the first.
> > So, now we're given our pair of declarations
> > template <class X, class T> void method (double u, T v);
> > template <class X> void method (double u, long v);
> > Let's check whether the first is more specialized than the second. > > For each type template parameter, we synthesize a *unique* type, i.e. > > we declare: > > class XX {}; class TT {}; > > and try matching the prototype > > method<XX> (double, TT); > > against the second template - it fails.
> That's where I don't see it, I guess. You're saying "it fails" because > the second one cannot be used since TT has no conversion to 'long', is > that it?
I agree with Victor here. In my understanding, it doesn't fail, but...
> > Now do it the other way around, and match > > method<XX> (double, long) > > against the first template - it succeeds and it is an exact match (T = > > long).
This one is an exact match! The function templates are:
(1) template <class X, class T> void method (double u, T v); (2) template <class X> void method (double u, long v);
So argument deduction for the call with X substituted by class A is successful for both cases.
Apparently, there's an ambiguity. However, the extra overload resolution criterion comes into play. Is there one of them that is "more specialized"?
Perhaps I'm being too simplistic. But in my opinion it's reasonable to assume that the second call is a perfect match. The compiler doesn't need to substitute template parameter T by the argument of type double. That's why I consider the second call to be "more specialized" than the first one.
> Perhaps I'm being too simplistic. But in my opinion it's reasonable to > assume that the second call is a perfect match. The compiler doesn't > need to substitute template parameter T by the argument of type > double. That's why I consider the second call to be "more specialized" > than the first one.
I meant to say the substitution of template parameter T by the argument of type long (not double).
> highegg wrote: > > On 15 Pro, 14:48, Victor Bazarov <v.Abaza...@comAcast.net> wrote: > >> highegg wrote: > >>> On 12 Pro, 19:42, Victor Bazarov <v.Abaza...@comAcast.net> wrote: > >>>> Victor Bazarov wrote: > >>>>> highegg wrote: > >>>>>> given the declarations > >>>>>> class A {}; > >>>>>> template <class X, class T> void method (double u, T v); > >>>>>> template <class X> void method (double u, long v); > >>>>>> ... > >>>>>> double u; long v; > >>>>>> Is the following call unambigous (w.r.t. C++ standard)? > >>>>>> method<A> (u, v); > >>>>>> [..] > >>>>> Yes. > >>>> I meant to say it was ambiguous. If you know what part of the Draft > >>>> says the second is a better match, could you point to it, please? > >>>> From what I figure, the first template could be more specialised than > >>>> the second because it has two types defined, not just one. However, all > >>>> the examples given in the Standard have to do with A<T*> vs A<T> (which > >>>> makes the former more specialised) and not A<T,U> vs A<T>. My > >>>> understanding of what makes templates "more specialised" can be > >>>> incorrect, so I'd appreciated somebody's explanation. > >>> Hi Victor, > >>> after reading the relevant sections thoroughly, I think it is the > >>> partial template ordering rules in 14.5.5.2 that account for the > >>> unambigous resolution. See the paragraphs 2-5. > >>> Simply said, the reasoning is that the second template's prototype can > >>> be matched by the first, but not vice versa (note the wording in > >>> paragraph 3 saying that a *unique* type is synthesized for each type > >>> template parameter, i.e. for T in this case). > >>> Therefore, the second template is more specialized and will be > >>> preferred. > >>> If anyone thinks I'm wrong with this reasoning, please clarify. > >>> Anyway, thanks to everyone who replied, especially Joe pointing me to > >>> Comeau C++. > >>> Jaroslav Hajek > >> Thanks, Jaroslav. I take it you meant 14.5.6.2 (not .5.2). I can't > >> find that reasoning you talk about (yes, I have read paragraphs 2-5 in > >> the [temp.func.order] section). Can you please lay your deductions down > >> so that my feeble brain can understand them? Apparently, somewhere in > >> the paragraph 3's first sentence I get lost. How does that sentence > >> explain that in your example the second template is more specialised? > >> Much appreciated!
> > Sorry. I was referring to the 1998 standard.
> Don't apologise, I was looking in the latest draft. My fault.
> > Anyway, I'm attaching the
> > relevant text:
> > 2. Given two overloaded function templates, whether one is more > > specialized than another can be determined by transforming each > > template in turn and using argument deduction (14.8.2) to compare it > > to the other. > > 3. The transformation used is: > > -- For each type template parameter, synthesize a unique type and > > substitute that for each occurrence of that parameter in the function > > parameter list, or for a template conversion function, in the return > > type. > > -- For each non-type template parameter... (not relevant) > > -- For each template template parameter...
> > 4. Using the transformed function parameter list, perform argument > > deduction against the other function template. The transformed > > template is at least as specialized as the other if, and only if, the > > deduction succeeds and the deduced parameter types are an exact match > > (so the deduction does not rely on implicit conversions).
> > 5. A template is more specialized than another if, and only if, it is > > at least as specialized as the other template and that template is not > > at least as specialized as the first.
> > So, now we're given our pair of declarations
> > template <class X, class T> void method (double u, T v);
> > template <class X> void method (double u, long v);
> > Let's check whether the first is more specialized than the second. > > For each type template parameter, we synthesize a *unique* type, i.e. > > we declare: > > class XX {}; class TT {}; > > and try matching the prototype > > method<XX> (double, TT); > > against the second template - it fails.
> That's where I don't see it, I guess. You're saying "it fails" because > the second one cannot be used since TT has no conversion to 'long', is > that it?
Yes. TT is a unique type, no conversions allowed. Remember there must be an exact match.
> > Now do it the other way around, and match > > method<XX> (double, long) > > against the first template - it succeeds and it is an exact match (T = > > long).
> OK, so the deduction succeeds means that the second is at least as > specialised as the first. And since before the first failed, it can't > be as specialised as the second, that means the second is more > specialised. Did I get that right?
I think so.
> > Therefore, by paragraph 4, the second template is at least as > > specialized as the first, and because the converse does not hold, the > > inequality is strict by paragraph 5.
> > At least, this is my understanding. Comments are welcome.
> Sounds reasonable. Thank you again for the explanation!
You're welcome. Thanks for bringing up the discussion - if you hadn't objected, I wouldn't have brought myself to actually analyze this.
> On 15 dez, 17:59, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> > highegg wrote: > > > On 15 Pro, 14:48, Victor Bazarov <v.Abaza...@comAcast.net> wrote: > > >> highegg wrote: > > >>> On 12 Pro, 19:42, Victor Bazarov <v.Abaza...@comAcast.net> wrote: > > >>>> Victor Bazarov wrote: > > >>>>> highegg wrote: > > >>>>>> given the declarations > > >>>>>> class A {}; > > >>>>>> template <class X, class T> void method (double u, T v); > > >>>>>> template <class X> void method (double u, long v); > > >>>>>> ... > > >>>>>> double u; long v; > > >>>>>> Is the following call unambigous (w.r.t. C++ standard)? > > >>>>>> method<A> (u, v); > > >>>>>> [..] > > >>>>> Yes. > > >>>> I meant to say it was ambiguous. If you know what part of the Draft > > >>>> says the second is a better match, could you point to it, please? > > >>>> From what I figure, the first template could be more specialised than > > >>>> the second because it has two types defined, not just one. However, all > > >>>> the examples given in the Standard have to do with A<T*> vs A<T> (which > > >>>> makes the former more specialised) and not A<T,U> vs A<T>. My > > >>>> understanding of what makes templates "more specialised" can be > > >>>> incorrect, so I'd appreciated somebody's explanation. > > >>> Hi Victor, > > >>> after reading the relevant sections thoroughly, I think it is the > > >>> partial template ordering rules in 14.5.5.2 that account for the > > >>> unambigous resolution. See the paragraphs 2-5. > > >>> Simply said, the reasoning is that the second template's prototype can > > >>> be matched by the first, but not vice versa (note the wording in > > >>> paragraph 3 saying that a *unique* type is synthesized for each type > > >>> template parameter, i.e. for T in this case). > > >>> Therefore, the second template is more specialized and will be > > >>> preferred. > > >>> If anyone thinks I'm wrong with this reasoning, please clarify. > > >>> Anyway, thanks to everyone who replied, especially Joe pointing me to > > >>> Comeau C++. > > >>> Jaroslav Hajek > > >> Thanks, Jaroslav. I take it you meant 14.5.6.2 (not .5.2). I can't > > >> find that reasoning you talk about (yes, I have read paragraphs 2-5 in > > >> the [temp.func.order] section). Can you please lay your deductions down > > >> so that my feeble brain can understand them? Apparently, somewhere in > > >> the paragraph 3's first sentence I get lost. How does that sentence > > >> explain that in your example the second template is more specialised? > > >> Much appreciated!
> I think the expression "more specialized" can be confusing in the > standard wording. Nevertheless, here's why I think there should be no > ambiguous call.
> > > Sorry. I was referring to the 1998 standard.
> > Don't apologise, I was looking in the latest draft. My fault.
> > > Anyway, I'm attaching the
> > > relevant text:
> > > 2. Given two overloaded function templates, whether one is more > > > specialized than another can be determined by transforming each > > > template in turn and using argument deduction (14.8.2) to compare it > > > to the other. > > > 3. The transformation used is: > > > -- For each type template parameter, synthesize a unique type and > > > substitute that for each occurrence of that parameter in the function > > > parameter list, or for a template conversion function, in the return > > > type. > > > -- For each non-type template parameter... (not relevant) > > > -- For each template template parameter...
> > > 4. Using the transformed function parameter list, perform argument > > > deduction against the other function template. The transformed > > > template is at least as specialized as the other if, and only if, the > > > deduction succeeds and the deduced parameter types are an exact match > > > (so the deduction does not rely on implicit conversions).
> > > 5. A template is more specialized than another if, and only if, it is > > > at least as specialized as the other template and that template is not > > > at least as specialized as the first.
> > > So, now we're given our pair of declarations
> > > template <class X, class T> void method (double u, T v);
> > > template <class X> void method (double u, long v);
> > > Let's check whether the first is more specialized than the second. > > > For each type template parameter, we synthesize a *unique* type, i.e. > > > we declare: > > > class XX {}; class TT {}; > > > and try matching the prototype > > > method<XX> (double, TT); > > > against the second template - it fails.
> > That's where I don't see it, I guess. You're saying "it fails" because > > the second one cannot be used since TT has no conversion to 'long', is > > that it?
> I agree with Victor here. In my understanding, it doesn't fail, but...
> > > Now do it the other way around, and match > > > method<XX> (double, long) > > > against the first template - it succeeds and it is an exact match (T = > > > long).
> This one is an exact match! The function templates are:
> (1) template <class X, class T> void method (double u, T v); > (2) template <class X> void method (double u, long v);
> So argument deduction for the call with X substituted by class A is > successful for both cases.
> Apparently, there's an ambiguity. However, the extra overload > resolution criterion comes into play. Is there one of them that is > "more specialized"?
Yes. See my discussion with Victor. Note that the partial ordering is independent of any function references made, including the possibly ambiguous one, it is solely a matter of the templates in question.
> Perhaps I'm being too simplistic. But in my opinion it's reasonable to > assume that the second call is a perfect match. The compiler doesn't > need to substitute template parameter T by the argument of type > double. That's why I consider the second call to be "more specialized" > than the first one.
Yes. In fact, that was my guess, too. The rules in standard are more general and cover this case. In fact, one may state the following C++ lemma (yes, I'm a mathematician):
Lemma: Given any function template, if you substitute any of its deductible type parameters by a particular type, the resulting template prototype is an unambiguous overload and is more specialized.