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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • mathieu

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

    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,P ixelType>(outpu tCurve);
    }

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


    Thanks !
  • Bo Persson

    #2
    Re: call of overloaded 'foo(short unsigned int*&amp;)' is ambiguous

    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,P ixelType>(outpu tCurve);
    }
    >
    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




    Comment

    • Andrey Tarasevich

      #3
      Re: call of overloaded 'foo(short unsigned int*&amp;)' is ambiguous

      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,P ixelType>(outpu tCurve);
      }
      >
      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

      Comment

      • James Kanze

        #4
        Re: call of overloaded 'foo(short unsigned int*&amp;)' is ambiguous

        On Nov 17, 6:33 pm, mathieu <mathieu.malate ...@gmail.comwr ote:
        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,P ixelType>(outpu tCurve);
        }
        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.kan ze@gmail.com
        Conseils en informatique orientée objet/
        Beratung in objektorientier ter Datenverarbeitu ng
        9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

        Comment

        Working...