[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

call of overloaded 'foo(short unsigned int*&)' is ambiguous

mathieu

11/17/2008 5:33:00 PM

Could someone please tell me what is wrong with the following -ugly-
piece of c++ code. Why when I explicititely set the template parameter
my gcc compiler start getting confused:

bla.cxx: In function 'int main()':
bla.cxx:25: error: call of overloaded 'foo(short unsigned int*&)' is
ambiguous
bla.cxx:2: note: candidates are: void foo(OutputType*) [with PixelType
= short unsigned int, OutputType = short unsigned int]
bla.cxx:10: note: void foo(PixelType*) [with PixelType
= short unsigned int]

with code:


template <class PixelType,class OutputType>
void foo(OutputType *outputCurve)
{
PixelType pt;
}

template <class PixelType>
void foo(PixelType *outputCurve)
{
foo<PixelType,PixelType>(outputCurve);
}

int main()
{
unsigned short *o = 0;
// foo(o); // ok
foo<unsigned short>(o); // not ok
return 0;
}


Thanks !
3 Answers

Bo Persson

11/17/2008 6:36:00 PM

0

mathieu wrote:
> Could someone please tell me what is wrong with the following -ugly-
> piece of c++ code. Why when I explicititely set the template
> parameter my gcc compiler start getting confused:
>
> bla.cxx: In function 'int main()':
> bla.cxx:25: error: call of overloaded 'foo(short unsigned int*&)' is
> ambiguous
> bla.cxx:2: note: candidates are: void foo(OutputType*) [with
> PixelType = short unsigned int, OutputType = short unsigned int]
> bla.cxx:10: note: void foo(PixelType*) [with
> PixelType = short unsigned int]
>
> with code:
>
>
> template <class PixelType,class OutputType>
> void foo(OutputType *outputCurve)
> {
> PixelType pt;
> }
>
> template <class PixelType>
> void foo(PixelType *outputCurve)
> {
> foo<PixelType,PixelType>(outputCurve);
> }
>
> int main()
> {
> unsigned short *o = 0;
> // foo(o); // ok
> foo<unsigned short>(o); // not ok
> return 0;
> }
>
>

In the call to foo<unsigned short>(o), you explicitly say that
PixelType is unsigned short.

The compiler says - what if OutputType is also unsigned short?


Bo Persson




Andrey Tarasevich

11/17/2008 7:17:00 PM

0

mathieu wrote:
> Could someone please tell me what is wrong with the following -ugly-
> piece of c++ code. Why when I explicititely set the template parameter
> my gcc compiler start getting confused:
>
> bla.cxx: In function 'int main()':
> bla.cxx:25: error: call of overloaded 'foo(short unsigned int*&)' is
> ambiguous
> bla.cxx:2: note: candidates are: void foo(OutputType*) [with PixelType
> = short unsigned int, OutputType = short unsigned int]
> bla.cxx:10: note: void foo(PixelType*) [with PixelType
> = short unsigned int]
>
> with code:
>
>
> template <class PixelType,class OutputType>
> void foo(OutputType *outputCurve)
> {
> PixelType pt;
> }
>
> template <class PixelType>
> void foo(PixelType *outputCurve)
> {
> foo<PixelType,PixelType>(outputCurve);
> }
>
> int main()
> {
> unsigned short *o = 0;
> // foo(o); // ok
> foo<unsigned short>(o); // not ok
> return 0;
> }
>

As you probably know, when you call a template function you are not
required to explicitly specify all template arguments. You can specify
none (in which case the compiler will try to deduce them), or you can
specify just a few of the leading arguments (in which case the compiler
will try to deduce the remaining ones).

In the first call

foo(o);

you don't specify any template arguments. The compiler considers both
versions of 'foo' template. In this case the compiler cannot use the
first version of 'foo' template as a candidate, because template
argument 'PixelType' is not deducible. The compiler is left with only
one candidate - the second version of 'foo' template - and successfully
uses it.

In the second call

foo<unsigned short>(o);

you specified one template argument. The compiler again considers both
versions of 'foo' template. This argument can be interpreted as the
first argument of the first 'foo' template (the one that was
non-deducible in the previous example). Since you specified it
explicitly, the compiler only has to deduce the second template
argument, which it can successfully do. So the first version becomes a
candidate in this case. The second version of 'foo' template is also a
candidate - with an explicitly specified argument. So now the compiler
has two candidates and both are equally good. Hence the ambiguity the
compiler is telling you about in its error messages.

However, it would be interesting to know whether C++ partial ordering
rules are supposed to resolve the ambiguity in this case. Is one of the
versions supposed to be recognized as "more specialized"? I'd say not,
based on what I see in C++98 specification. But Comeau Online compiler
seems to resolve the call in favor of the two-parameter version without
complaining about any ambiguities.

--
Best regards,
Andrey Tarasevich

James Kanze

11/18/2008 8:42:00 AM

0

On Nov 17, 6:33 pm, mathieu <mathieu.malate...@gmail.com> wrote:
> Could someone please tell me what is wrong with the following
> -ugly- piece of c++ code. Why when I explicititely set the
> template parameter my gcc compiler start getting confused:

> bla.cxx: In function 'int main()':
> bla.cxx:25: error: call of overloaded 'foo(short unsigned int*&)' is
> ambiguous
> bla.cxx:2: note: candidates are: void foo(OutputType*) [with PixelType
> = short unsigned int, OutputType = short unsigned int]
> bla.cxx:10: note: void foo(PixelType*) [with PixelType
> = short unsigned int]

The compiler isn't confused; it's just doing what the standard
requires:-).

> with code:

> template <class PixelType,class OutputType>
> void foo(OutputType *outputCurve)
> {
> PixelType pt;
> }

> template <class PixelType>
> void foo(PixelType *outputCurve)
> {
> foo<PixelType,PixelType>(outputCurve);
> }

> int main()
> {
> unsigned short *o = 0;
> // foo(o); // ok
> foo<unsigned short>(o); // not ok
> return 0;
> }

OK. You have two function templates named foo, which will be
considered each time you invoke a function named foo; overload
resolution will determine which one is chosen. Strictly
speaking, function overload chooses between functions, not
between function templates; when you call a function for which
there are function templates, the compiler tries to deduce the
template arguments for each function template, and if it
succeeds, it adds the instantation (the instantiation of a
function template is a function) to the overload set.

In the first case, foo(o), template argument deduction fails for
the first function template; the compiler cannot deduce the type
of PixelType, so no function is added. It succeeds for the
second, with unsigned short for PixelType, the the function
foo<unsigned short>( unsigned short* ) is added to the overload
set. Since the overload set only contains a single function,
there is no ambiguity.

In the second case, where you call foo<unsigned short>, the
procedure is exactly the same. Except that argument deduction
works for both of the functions; for the first, it gives an
instantiation of foo<unsigned short, unsigned short>, and for
the second, an instantiation of foo<unsigned short>. (For the
second, there's really not much to deduce in the usual sense of
the word, but formally, deduction takes place, and the results
are added to the overload set.) The result is that you end up
with two functions with the same parameter, which results in an
ambiguity from overload resolution.

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34