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

Discussion in 'C++' started by mathieu, Nov 17, 2008.

  1. mathieu

    mathieu Guest

    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 !
    mathieu, Nov 17, 2008
    #1
    1. Advertising

  2. mathieu

    Bo Persson Guest

    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
    Bo Persson, Nov 17, 2008
    #2
    1. Advertising

  3. 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
    Andrey Tarasevich, Nov 17, 2008
    #3
  4. mathieu

    James Kanze Guest

    On Nov 17, 6:33 pm, 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]


    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:
    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
    James Kanze, Nov 18, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Gunnar

    int foo and int foo()

    Gunnar, Jan 19, 2004, in forum: C++
    Replies:
    8
    Views:
    368
    Robert Paul Clark
    Jan 22, 2004
  2. Replies:
    3
    Views:
    375
    John Roth
    Jul 29, 2005
  3. .rhavin grobert

    vector: Foo[5] == ((foo*)Foo) + 5 ?

    .rhavin grobert, Sep 23, 2008, in forum: C++
    Replies:
    4
    Views:
    382
    JaredGrubb
    Sep 24, 2008
  4. pozz
    Replies:
    12
    Views:
    726
    Tim Rentsch
    Mar 20, 2011
  5. Replies:
    4
    Views:
    135
    Thomas 'PointedEars' Lahn
    Dec 23, 2007
Loading...

Share This Page