Overload resolution of function templates

Discussion in 'C++' started by matthias.neubauer@gmail.com, Oct 3, 2008.

  1. Guest

    I have problems understanding how overloading of function templates
    works.

    Consider first the following code without any function templates ...

    int foo(const char *& c)
    {
    return 0;
    }

    int foo(const char *c)
    {
    return 1;
    }

    int main() {
    const char * s = "Hi!";
    return foo(s);
    }

    Overloading resolution of foo is ambiguous, as can be witness by e.g. g
    ++

    Foo.cpp: In function 'int main()':
    Foo.cpp:14: error: call of overloaded 'foo(const char*&)' is ambiguous
    Foo.cpp:2: note: candidates are: int foo(const char*&)
    Foo.cpp:7: note: int foo(const char*)

    If I now use function templates for foo, foo_t, as follows

    template<typename C>
    int foo_t(C& c)
    {
    return 0;
    }

    template<typename C>
    int foo_t(const C *c)
    {
    return 1;
    }

    int main() {
    const char * s = "Hi!";
    return foo_t(s);
    }

    some implementations I tested (g++, msvc) seem to find a best
    candidate function for foo_i which I do not understand.

    As I read 13.3.1 para 7 of the standard, I would expect an
    implementation to first determine specializations for foo_t (here:
    foo_t<const char *> and foo_t<char> resp.), and then proceed as above.
    Hence, I'd also expect an ambiguity error here. Where is my
    misunderstanding?

    Cheers,

    Matthias
     
    , Oct 3, 2008
    #1
    1. Advertising

  2. mojumbo Guest

    On Oct 3, 10:07 am, wrote:
    > I have problems understanding how overloading of function templates
    > works.
    >
    > Consider first the following code without any function templates ...
    >
    > int foo(const char *& c)
    > {
    > return 0;
    > }
    >
    > int foo(const char *c)
    > {
    > return 1;
    > }
    >
    > int main() {
    > const char * s = "Hi!";
    > return foo(s);
    > }
    >
    > template<typename C>
    > int foo_t(C& c)
    > {
    > return 0;
    > }
    >
    > template<typename C>
    > int foo_t(const C *c)
    > {
    > return 1;
    > }
    >
    > int main() {
    > const char * s = "Hi!";
    > return foo_t(s);
    > }
    >
    > some implementations I tested (g++, msvc) seem to find a best
    > candidate function for foo_i which I do not understand.
    >
    > As I read 13.3.1 para 7 of the standard, I would expect an
    > implementation to first determine specializations for foo_t (here:
    > foo_t<const char *> and foo_t<char> resp.), and then proceed as above.
    > Hence, I'd also expect an ambiguity error here. Where is my
    > misunderstanding?


    The specializations are determined but now your function arguments
    have changed. The two methods become:

    int foot_t(const char*&)
    and
    int foo_t(const char**)

    So if you're passing in a const char* my expectation would be the
    foo_t(const char*&) method is called
     
    mojumbo, Oct 3, 2008
    #2
    1. Advertising

  3. Rolf Magnus Guest

    mojumbo wrote:

    > On Oct 3, 10:07 am, wrote:
    >> I have problems understanding how overloading of function templates
    >> works.
    >>
    >> Consider first the following code without any function templates ...
    >>
    >> int foo(const char *& c)
    >> {
    >> return 0;
    >> }
    >>
    >> int foo(const char *c)
    >> {
    >> return 1;
    >> }
    >>
    >> int main() {
    >> const char * s = "Hi!";
    >> return foo(s);
    >> }
    >>
    >> template<typename C>
    >> int foo_t(C& c)
    >> {
    >> return 0;
    >> }
    >>
    >> template<typename C>
    >> int foo_t(const C *c)
    >> {
    >> return 1;
    >> }
    >>
    >> int main() {
    >> const char * s = "Hi!";
    >> return foo_t(s);
    >> }
    >>
    >> some implementations I tested (g++, msvc) seem to find a best
    >> candidate function for foo_i which I do not understand.
    >>
    >> As I read 13.3.1 para 7 of the standard, I would expect an
    >> implementation to first determine specializations for foo_t (here:
    >> foo_t<const char *> and foo_t<char> resp.), and then proceed as above.
    >> Hence, I'd also expect an ambiguity error here. Where is my
    >> misunderstanding?

    >
    > The specializations are determined but now your function arguments
    > have changed. The two methods become:
    >
    > int foot_t(const char*&)
    > and
    > int foo_t(const char**)


    Why? foo_t(const char**) wouldn't fit, and it wouldn't even be a possible
    template instance (what would the template argument C be?).
    But foo_t(const char*) would fit (with C=char). And actually, my compiler is
    choosing that one.
     
    Rolf Magnus, Oct 3, 2008
    #3
  4. On Oct 3, 3:07 pm, wrote:
    > I have problems understanding how overloading of function templates
    > works.
    > [...]
    > As I read 13.3.1 para 7 of the standard, I would expect an
    > implementation to first determine specializations for foo_t (here:
    > foo_t<const char *> and foo_t<char> resp.), and then proceed as above.
    > Hence, I'd also expect an ambiguity error here. Where is my
    > misunderstanding?


    When function templates are involved then selection is based on which
    candidate is more specialized. See "13.3.3 Best Viable Function" and
    "14.5.6.2 Partial ordering of function templates" (Draft C++ Standard,
    N2723).

    For example,

    template <class T> void foo (T a); // #1
    template <class T> void foo (T* a); // #2, more specialized
    int* a; foo (a); // selects #2

    Regards,
    Vidar Hasfjord
     
    Vidar Hasfjord, Oct 3, 2008
    #4
  5. Guest

    On Oct 3, 5:50 pm, Vidar Hasfjord <> wrote:

    > When function templates are involved then selection is based on which
    > candidate is more specialized. See "13.3.3 Best Viable Function" and
    > "14.5.6.2 Partial ordering of function templates" (Draft C++ Standard,
    > N2723).


    Ok, now I see. [over.match.best] compares function template
    specializations differently. That's the part I was missing. Thanks!
     
    , Oct 3, 2008
    #5
  6. On Fri, 03 Oct 2008 16:07:46 +0200, <> wrote:

    > I have problems understanding how overloading of function templates
    > works.
    >


    .... snip ...

    > If I now use function templates for foo, foo_t, as follows
    >
    > template<typename C>
    > int foo_t(C& c)
    > {
    > return 0;
    > }
    >
    > template<typename C>
    > int foo_t(const C *c)
    > {
    > return 1;
    > }
    >
    > int main() {
    > const char * s = "Hi!";
    > return foo_t(s);
    > }
    >
    > some implementations I tested (g++, msvc) seem to find a best
    > candidate function for foo_i which I do not understand.
    >
    > As I read 13.3.1 para 7 of the standard, I would expect an
    > implementation to first determine specializations for foo_t (here:
    > foo_t<const char *> and foo_t<char> resp.), and then proceed as above.
    > Hence, I'd also expect an ambiguity error here. Where is my
    > misunderstanding?


    The reason why there is no ambiguity, is because the two functions are
    ordered by the partial ordering of functions. That is, the second template
    is more specialized than the first. That is possible because, when
    matching (const C*) against C&, the reference is stripped from C& (see
    14.8.2.1/2). If you call foo_t(1) [eg. calling the C& version with an
    rvalue], overload resolution succeeds, but the call fails.

    Regards
    Jiri Palecek
     
    Jiøí Paleèek, Oct 3, 2008
    #6
  7. Guest

    On Oct 3, 7:42 pm, Jiøí Paleèek <> wrote:
    > On Fri, 03 Oct 2008 16:07:46 +0200, <> wrote:


    > > template<typename C>
    > > int foo_t(C& c)
    > > {
    > > return 0;
    > > }

    >
    > > template<typename C>
    > > int foo_t(const C *c)
    > > {
    > > return 1;
    > > }

    >
    > > int main() {
    > > const char * s = "Hi!";
    > > return foo_t(s);
    > > }


    > The reason why there is no ambiguity, is because the two functions are
    > ordered by the partial ordering of functions. That is, the second template
    > is more specialized than the first. That is possible because, when
    > matching (const C*) against C&, the reference is stripped from C& (see
    > 14.8.2.1/2). If you call foo_t(1) [eg. calling the C& version with an
    > rvalue], overload resolution succeeds, but the call fails.


    ALright. I am still a little bit confused. As you say, when comparing
    function templates ("14.5.5.2 partial ordering of function
    templates"), we perform argument deduction. But 14.5.5.2p4 also
    dictates

    "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)."

    What exactly does the term "exact match" mean in this context? Is this
    specified somewhere else?

    In my example above, as I understand it, the deduced parameter type
    for (C&) is

    const C*&

    which is NOT an exact match to

    const C*.

    Instead, we MUST use an implicit conversion to strip away the
    reference.

    Or, does the term "exact match" mean here, we still compare the
    deduced parameter type and the expected parameter type "inexactly" by
    ignoring
    some parts as specified in 14.8.2.1?

    -Matthias
     
    , Oct 7, 2008
    #7
  8. Triple-DES Guest

    On 7 Okt, 12:45, wrote:
    > On Oct 3, 7:42 pm, Jiøí Paleèek <> wrote:
    >
    >
    >
    >
    >
    > > On Fri, 03 Oct 2008 16:07:46 +0200, <> wrote:
    > > >   template<typename C>
    > > >   int foo_t(C& c)
    > > >   {
    > > >    return 0;
    > > >   }

    >
    > > >   template<typename C>
    > > >   int foo_t(const C *c)
    > > >   {
    > > >    return 1;
    > > >   }

    >
    > > >   int main() {
    > > >     const char * s = "Hi!";
    > > >     return foo_t(s);
    > > >   }

    > > The reason why there is no ambiguity, is because the two functions are
    > > ordered by the partial ordering of functions. That is, the second template
    > > is more specialized than the first. That is possible because, when
    > > matching (const C*) against C&, the reference is stripped from C& (see
    > > 14.8.2.1/2). If you call foo_t(1) [eg. calling the C& version with an
    > > rvalue], overload resolution succeeds, but the call fails.

    >
    > ALright. I am still a little bit confused. As you say, when comparing
    > function templates ("14.5.5.2 partial ordering of function
    > templates"), we perform argument deduction. But 14.5.5.2p4 also
    > dictates
    >
    >   "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)."
    >
    > What exactly does the term "exact match" mean in this context? Is this
    > specified somewhere else?
    >
    > In my example above, as I understand it, the deduced parameter type
    > for (C&) is
    >
    >    const C*&
    >
    > which is NOT an exact match to
    >
    >    const C*.
    >
    > Instead, we MUST use an implicit conversion to strip away the
    > reference.
    >
    > Or, does the term "exact match" mean here, we still compare the
    > deduced parameter type and the expected parameter type "inexactly" by
    > ignoring
    > some parts as specified in 14.8.2.1?
    >
    > -Matthias


    Yes, there is a special case for reference binding, so that the
    conversion from const C* to const C*& has "Exact Match" ranking.
     
    Triple-DES, Oct 7, 2008
    #8
    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. Eph0nk

    Error: Overload resolution failed

    Eph0nk, Oct 23, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    1,866
    Eph0nk
    Oct 23, 2003
  2. Piotre Ugrumov
    Replies:
    3
    Views:
    375
    Nick Hounsome
    Jan 25, 2004
  3. JKop
    Replies:
    3
    Views:
    484
  4. recover
    Replies:
    2
    Views:
    820
    recover
    Jul 25, 2006
  5. Ying-Chieh Liao

    function overload (not operator overload)

    Ying-Chieh Liao, Oct 11, 2004, in forum: Perl Misc
    Replies:
    3
    Views:
    255
    Sherm Pendley
    Oct 11, 2004
Loading...

Share This Page