template overload resolution

Discussion in 'C++' started by Victor Bazarov, Jul 31, 2007.

  1. hurcan solter wrote:
    > given the code snippet;
    >
    > template<typename T>
    > void foo(T,T){}
    >
    > template<typename T1,typename T2>
    > void foo(T1*,T2*){}
    >
    > int main( ) {
    >
    > foo((int*)0,(int*)0);
    >
    > }
    >
    > Could anyone please explain me why the second template is not more
    > viable for overload resolution?
    > AFAIK each argument is matched with corresponding parameter. in that
    > case shouldnt T1* and T2* match better than T for (int*)? I assume T1
    > and T2 are disjoint aren't they? or must they be different types?


    A template with fewer arguments is considered more specialised than one
    with more arguments, I guess. The more arguments a template has, the
    more generic it is.

    Those are just guesses, of course. I don't have time to look through
    the Standard for confirmation.

    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, Jul 31, 2007
    #1
    1. Advertising

  2. given the code snippet;

    template<typename T>
    void foo(T,T){}

    template<typename T1,typename T2>
    void foo(T1*,T2*){}

    int main( ) {

    foo((int*)0,(int*)0);

    }

    Could anyone please explain me why the second template is not more
    viable for overload resolution?
    AFAIK each argument is matched with corresponding parameter. in that
    case shouldnt T1* and T2* match better than T for (int*)? I assume T1
    and T2 are disjoint aren't they? or must they be different types?

    Thanks in advance.


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    hurcan solter, Jul 31, 2007
    #2
    1. Advertising


  3. > A template with fewer arguments is considered more specialised than one
    > with more arguments, I guess. The more arguments a template has, the
    > more generic it is.
    >
    > Those are just guesses, of course. I don't have time to look through
    > the Standard for confirmation.
    >

    Well, in fact the call is ambiguous.it's unambiguous if i define
    foo(T*,T*)
    which suggests that,there is also a relation between argument that it
    prevents from
    one preferred over another.
     
    hurcan solter, Jul 31, 2007
    #3
  4. Hendrik Schober wrote:
    > hurcan solter <> wrote:
    >> given the code snippet;
    >>
    >> template<typename T>
    >> void foo(T,T){}
    >>
    >> template<typename T1,typename T2>
    >> void foo(T1*,T2*){}
    >>
    >> int main( ) {
    >>
    >> foo((int*)0,(int*)0);
    >>
    >> }
    >>
    >> Could anyone please explain me why the second template is not more
    >> viable for overload resolution?
    >> [...]

    >
    > From <http://www.comeaucomputing.com/tryitout/>:
    >
    > Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
    > Copyright 1988-2007 Comeau Computing. All rights reserved.
    > MODE:strict errors C++ C++0x_extensions
    >
    > "ComeauTest.c", line 9: error: more than one instance of overloaded
    > function "foo"
    > matches the argument list, the choices that match are:
    > function template "void foo(T, T)"
    > function template "void foo(T1 *, T2 *)"
    > The argument types that you used are: (int *, int *)
    > foo((int*)0,(int*)0);
    > ^
    >
    > 1 error detected in the compilation of "ComeauTest.c".
    >
    >> Thanks in advance.

    >
    > HTH,
    >
    > Schobi


    Could you perhaps enlighten us how this explains *why* the second
    template is *not* more viable?

    Thanks!

    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, Jul 31, 2007
    #4
  5. Victor Bazarov <> wrote:
    > Hendrik Schober wrote:
    > > hurcan solter <> wrote:
    > > > given the code snippet;
    > > >
    > > > template<typename T>
    > > > void foo(T,T){}
    > > >
    > > > template<typename T1,typename T2>
    > > > void foo(T1*,T2*){}
    > > >
    > > > int main( ) {
    > > >
    > > > foo((int*)0,(int*)0);
    > > >
    > > > }
    > > >

    > [...]
    > >
    > > From <http://www.comeaucomputing.com/tryitout/>:
    > >
    > > Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
    > > Copyright 1988-2007 Comeau Computing. All rights reserved.
    > > MODE:strict errors C++ C++0x_extensions
    > >
    > > "ComeauTest.c", line 9: error: more than one instance of overloaded
    > > function "foo"
    > > matches the argument list, the choices that match are:
    > > function template "void foo(T, T)"
    > > function template "void foo(T1 *, T2 *)"
    > > The argument types that you used are: (int *, int *)
    > > foo((int*)0,(int*)0);
    > > ^
    > >
    > > 1 error detected in the compilation of "ComeauTest.c".
    > >
    > > > Thanks in advance.

    > >
    > > HTH,
    > >
    > > Schobi

    >
    > Could you perhaps enlighten us how this explains *why* the second
    > template is *not* more viable?


    I don't think I can.
    I /guessed/ neither specialization to be more viable.
    I tried Comeau and found it agreeing with my guess.
    So I posted Comeau's opinion on the matter. (When I
    did this, my news server didn't have your reply yet,
    so I wasn't trying to contradict you.)

    Schobi

    --
    is never read
    I'm HSchober at gmx dot de
    "If there were some arcane way to remove the heads of every
    newsgroup troll on the planet, I think it would elevate
    humans to a whole new level of intelligence."
    Rocky Frisco
     
    Hendrik Schober, Jul 31, 2007
    #5
  6. hurcan solter <> wrote:
    > given the code snippet;
    >
    > template<typename T>
    > void foo(T,T){}
    >
    > template<typename T1,typename T2>
    > void foo(T1*,T2*){}
    >
    > int main( ) {
    >
    > foo((int*)0,(int*)0);
    >
    > }
    >
    > Could anyone please explain me why the second template is not more
    > viable for overload resolution?
    > [...]


    From <http://www.comeaucomputing.com/tryitout/>:

    Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
    Copyright 1988-2007 Comeau Computing. All rights reserved.
    MODE:strict errors C++ C++0x_extensions

    "ComeauTest.c", line 9: error: more than one instance of overloaded
    function "foo"
    matches the argument list, the choices that match are:
    function template "void foo(T, T)"
    function template "void foo(T1 *, T2 *)"
    The argument types that you used are: (int *, int *)
    foo((int*)0,(int*)0);
    ^

    1 error detected in the compilation of "ComeauTest.c".

    > Thanks in advance.


    HTH,

    Schobi

    --
    is never read
    I'm HSchober at gmx dot de
    "If there were some arcane way to remove the heads of every
    newsgroup troll on the planet, I think it would elevate
    humans to a whole new level of intelligence."
    Rocky Frisco



    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    Hendrik Schober, Jul 31, 2007
    #6
  7. Hendrik Schober wrote:
    > Victor Bazarov <> wrote:
    >> Hendrik Schober wrote:
    >>> hurcan solter <> wrote:
    >>>> given the code snippet;
    >>>>
    >>>> template<typename T>
    >>>> void foo(T,T){}
    >>>>
    >>>> template<typename T1,typename T2>
    >>>> void foo(T1*,T2*){}
    >>>>
    >>>> int main( ) {
    >>>>
    >>>> foo((int*)0,(int*)0);
    >>>>
    >>>> }
    >>>>

    >> [...]
    >>>
    >>> From <http://www.comeaucomputing.com/tryitout/>:
    >>>
    >>> Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for
    >>> ONLINE_EVALUATION_BETA1 Copyright 1988-2007 Comeau Computing. All
    >>> rights reserved. MODE:strict errors C++ C++0x_extensions
    >>>
    >>> "ComeauTest.c", line 9: error: more than one instance of overloaded
    >>> function "foo"
    >>> matches the argument list, the choices that match are:
    >>> function template "void foo(T, T)"
    >>> function template "void foo(T1 *, T2 *)"
    >>> The argument types that you used are: (int *, int *)
    >>> foo((int*)0,(int*)0);
    >>> ^
    >>>
    >>> 1 error detected in the compilation of "ComeauTest.c".
    >>>
    >>>> Thanks in advance.
    >>>
    >>> HTH,
    >>>
    >>> Schobi

    >>
    >> Could you perhaps enlighten us how this explains *why* the second
    >> template is *not* more viable?

    >
    > I don't think I can.
    > I /guessed/ neither specialization to be more viable.
    > I tried Comeau and found it agreeing with my guess.
    > So I posted Comeau's opinion on the matter. (When I
    > did this, my news server didn't have your reply yet,
    > so I wasn't trying to contradict you.)


    Please do contradict, I am all for a healthy discussion. Besides, my
    answer was just a guess, I am not even sure it is correct unless it's
    confirmed or proven wrong.

    The reason I am asking is that it seems that your reply is essentially
    giving the answer "because Comeau C++ says it is" to the 'why' question.
    My understanding is that the OP had already found out that the second
    function template was not more viable, you simply confirmed what the OP
    already knew, *OR* I misunderstood something (which happens more often
    as I grow older, unfortunately), and then I need to be shown the light.

    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, Jul 31, 2007
    #7
  8. Victor Bazarov <> wrote:
    > Hendrik Schober wrote:
    > > Victor Bazarov <> wrote:
    > > > Hendrik Schober wrote:
    > > > > hurcan solter <> wrote:
    > > > > > given the code snippet;
    > > > > >
    > > > > > template<typename T>
    > > > > > void foo(T,T){}
    > > > > >
    > > > > > template<typename T1,typename T2>
    > > > > > void foo(T1*,T2*){}
    > > > > >
    > > > > > int main( ) {
    > > > > >
    > > > > > foo((int*)0,(int*)0);
    > > > > >
    > > > > > }
    > > > > >
    > > > [...]
    > > > >
    > > > > From <http://www.comeaucomputing.com/tryitout/>:
    > > > >
    > > > > Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for
    > > > > ONLINE_EVALUATION_BETA1 Copyright 1988-2007 Comeau Computing. All
    > > > > rights reserved. MODE:strict errors C++ C++0x_extensions
    > > > >
    > > > > "ComeauTest.c", line 9: error: more than one instance of overloaded
    > > > > function "foo"
    > > > > matches the argument list, the choices that match are:
    > > > > function template "void foo(T, T)"
    > > > > function template "void foo(T1 *, T2 *)"
    > > > > The argument types that you used are: (int *, int *)
    > > > > foo((int*)0,(int*)0);
    > > > > ^
    > > > >
    > > > > 1 error detected in the compilation of "ComeauTest.c".
    > > > >
    > > > > > Thanks in advance.
    > > > >
    > > > > HTH,
    > > > >
    > > > > Schobi
    > > >
    > > > Could you perhaps enlighten us how this explains *why* the second
    > > > template is *not* more viable?

    > >
    > > I don't think I can.
    > > I /guessed/ neither specialization to be more viable.


    These aren't specializations, but overloaded
    functions. (No partial specialization of
    function templates. I know. Damn.)

    > > I tried Comeau and found it agreeing with my guess.
    > > So I posted Comeau's opinion on the matter. (When I
    > > did this, my news server didn't have your reply yet,
    > > so I wasn't trying to contradict you.)

    >
    > Please do contradict, I am all for a healthy discussion. Besides, my
    > answer was just a guess, I am not even sure it is correct unless it's
    > confirmed or proven wrong.


    My answer was just a guess, tooI wouldn't know chapter
    and verse, but this

    template<typename T>
    void foo(T,T){}

    template<typename T1,typename T2>
    void foo(T1*,T2*){}

    int main()
    {
    foo((int*)0,(int*)0);
    }

    looks to me as if neither overloaded version is
    a better fit than the other -- which is why I
    asked Comeau to confirm. .

    > The reason I am asking is that it seems that your reply is essentially
    > giving the answer "because Comeau C++ says it is" to the 'why' question.
    > My understanding is that the OP had already found out that the second
    > function template was not more viable, you simply confirmed what the OP
    > already knew, *OR* I misunderstood something (which happens more often
    > as I grow older, unfortunately), and then I need to be shown the light.


    I'm sorry I wasn't making my opinion clearer. I
    assumed that neither function template was a
    better fit. I thought posting an error message
    that says exactly that would make that clear. I
    should probably have been more explicit, though.

    > V


    Schobi

    --
    is never read
    I'm HSchober at gmx dot de
    "If there were some arcane way to remove the heads of every
    newsgroup troll on the planet, I think it would elevate
    humans to a whole new level of intelligence."
    Rocky Frisco
     
    Hendrik Schober, Jul 31, 2007
    #8
  9. Victor Bazarov

    James Kanze Guest

    On Jul 31, 5:41 pm, "Victor Bazarov" <> wrote:
    > hurcan solter wrote:
    > > given the code snippet;


    > > template<typename T>
    > > void foo(T,T){}


    > > template<typename T1,typename T2>
    > > void foo(T1*,T2*){}


    > > int main( ) {
    > > foo((int*)0,(int*)0);
    > > }


    > > Could anyone please explain me why the second template is not more
    > > viable for overload resolution?
    > > AFAIK each argument is matched with corresponding parameter. in that
    > > case shouldnt T1* and T2* match better than T for (int*)? I assume T1
    > > and T2 are disjoint aren't they? or must they be different types?


    > A template with fewer arguments is considered more specialised than one
    > with more arguments, I guess. The more arguments a template has, the
    > more generic it is.


    I think that the original poster was expecting the partial
    ordering of function templates, described in §14.5.6.2 to enter
    into play. I'll admit that I have great difficulty in
    understanding this myself, but roughly speaking, I think the
    idea is that the one function template is more specialized than
    another if all of its specializations could also be valid
    specializations of the other. Thus, for example, in:

    template< typename T > void f( T ) ;
    template< typename T > void f( T* ) ;

    the second is more specialized, because all possible
    specializations of it could also be specializations of the
    first, where as the reverse is not true.

    If this is really an accurate description, his functions
    obviously aren't ordered, since it is trivial to find
    specializations of one which can't possibly be a specialization
    of the other, e.g.: foo( int, int ) can only specialize the
    first, and foo( int*, double* ) can only specialize the second.

    *IF* I understand it correctly (and as I say, this is so abtuse
    that I'm far from sure), the partial ordering is present over
    the function templates themselves, independantly of any
    particular attempts to specialize.

    > Those are just guesses, of course. I don't have time to look through
    > the Standard for confirmation.


    I think at a higher level, you've given the best possible
    answer. If even better than average programmers have to study
    the standard to figure out what is going on, then your code is
    too complex, and you should avoid such constructs.

    --
    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, Jul 31, 2007
    #9
  10. Victor Bazarov

    Craig Scott Guest

    On Aug 1, 2:19 am, hurcan solter <> wrote:
    > template<typename T>
    > void foo(T,T){}
    >
    > template<typename T1,typename T2>
    > void foo(T1*,T2*){}
    >
    > int main( ) {
    >
    > foo((int*)0,(int*)0);
    >
    > }
    >
    > Could anyone please explain me why the second template is not more
    > viable for overload resolution?
    > AFAIK each argument is matched with corresponding parameter. in that
    > case shouldnt T1* and T2* match better than T for (int*)? I assume T1
    > and T2 are disjoint aren't they? or must they be different types?


    As far as the compiler is concerned, both can be matched equally well.
    No conversions are involved in either case, so there is no reason for
    the compiler to favour one over the other. You might be getting
    confused with *class* partial specialization. Eg
    #include <iostream>

    template<typename T>
    class Bar
    {
    public:
    Bar() { std::cout << "(1)" << std::endl; }
    };

    template<typename T>
    class Bar<T*>
    {
    public:
    Bar() { std::cout << "(2)" << std::endl; }
    };

    int main()
    {
    Bar<int> barInt; // Prints (1)
    Bar<int*> barIntPtr; // Prints (2)
    }

    --
    Computational Modeling, CSIRO (CMIS)
    Melbourne, Australia


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    Craig Scott, Aug 1, 2007
    #10
  11. Victor Bazarov

    James Kanze Guest

    On Aug 1, 7:18 am, Craig Scott <> wrote:
    > On Aug 1, 2:19 am, hurcan solter <> wrote:


    > > template<typename T>
    > > void foo(T,T){}


    > > template<typename T1,typename T2>
    > > void foo(T1*,T2*){}


    > > int main( ) {
    > > foo((int*)0,(int*)0);
    > > }


    > > Could anyone please explain me why the second template is not more
    > > viable for overload resolution?
    > > AFAIK each argument is matched with corresponding parameter. in that
    > > case shouldnt T1* and T2* match better than T for (int*)? I assume T1
    > > and T2 are disjoint aren't they? or must they be different types?


    > As far as the compiler is concerned, both can be matched equally well.


    In this case. If the choice were between:
    template< typename T >
    void foo( T, T ) ;
    and
    template< typename T >
    void foo( T*, T* ) ;
    however, there is a partial ordering of template
    "specializations" which comes into play: basically, given two
    function templates, if any time type deduction works for the
    first, it works for the second, but there are cases where type
    deduction can work for the second, but not for the first, then
    the first is said to be "more specialized" than the second.
    (Note that the use of "specialized" here has nothing to do with
    template specialization.)

    > No conversions are involved in either case, so there is no
    > reason for the compiler to favour one over the other.


    There isn't in this particular case, but there might be in other
    cases. There is a partial ordering among function templates,
    and that ordering does play a role in overload resolution.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientie objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34



    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    James Kanze, Aug 1, 2007
    #11
  12. Victor Bazarov

    Craig Scott Guest

    On Aug 1, 3:18 pm, Craig Scott <> wrote:
    > On Aug 1, 2:19 am, hurcan solter <> wrote:
    >
    >
    >
    > > template<typename T>
    > > void foo(T,T){}

    >
    > > template<typename T1,typename T2>
    > > void foo(T1*,T2*){}

    >
    > > int main( ) {

    >
    > > foo((int*)0,(int*)0);

    >
    > > }

    >
    > > Could anyone please explain me why the second template is not more
    > > viable for overload resolution?
    > > AFAIK each argument is matched with corresponding parameter. in that
    > > case shouldnt T1* and T2* match better than T for (int*)? I assume T1
    > > and T2 are disjoint aren't they? or must they be different types?

    >
    > As far as the compiler is concerned, both can be matched equally well.
    > No conversions are involved in either case, so there is no reason for
    > the compiler to favour one over the other.


    Sorry to reply to my own post, but after reading some of the other
    replies on comp.lang.c++ I thought it worth adding some more info. The
    partial ordering rules for function templates are given in section
    14.5.5.2 of the C++ standard. In particular:

    14.5.5.2/4: "... 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)."

    14.5.5.2/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 in the case presented by the original post, since there are no
    implicit conversions needed for either function, neither is considered
    more specialized than the other and the overload is ambiguous.

    HTH

    --
    Computational Modeling, CSIRO (CMIS)
    Melbourne, Australia


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    Craig Scott, Aug 1, 2007
    #12
  13. Victor Bazarov

    James Kanze Guest

    On Aug 1, 10:22 pm, Craig Scott <> wrote:
    > On Aug 1, 3:18 pm, Craig Scott <> wrote:
    > > On Aug 1, 2:19 am, hurcan solter <> wrote:


    > > > template<typename T>
    > > > void foo(T,T){}


    > > > template<typename T1,typename T2>
    > > > void foo(T1*,T2*){}


    > > > int main( ) {
    > > > foo((int*)0,(int*)0);
    > > > }


    > > > Could anyone please explain me why the second template is not more
    > > > viable for overload resolution?
    > > > AFAIK each argument is matched with corresponding parameter. in

    that
    > > > case shouldnt T1* and T2* match better than T for (int*)? I assume T1
    > > > and T2 are disjoint aren't they? or must they be different types?


    > > As far as the compiler is concerned, both can be matched equally well.
    > > No conversions are involved in either case, so there is no reason for
    > > the compiler to favour one over the other.


    > Sorry to reply to my own post, but after reading some of the other
    > replies on comp.lang.c++ I thought it worth adding some more info. The
    > partial ordering rules for function templates are given in section
    > 14.5.5.2 of the C++ standard. In particular:


    > 14.5.5.2/4: "... 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)."


    > 14.5.5.2/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."


    You're quoting out of context. '14.5.5.2 is incredibly
    difficult to understand, but one thing is clear: it establishes
    a partial ordering over the function templates themselves,
    independantly of the actual instantiations.

    > So in the case presented by the original post, since there are no
    > implicit conversions needed for either function, neither is considered
    > more specialized than the other and the overload is ambiguous.


    Whether implicit conversions are needed or not for a specific
    call has nothing to do with the ordering between the function
    templates. In fact, the ordering between the function templates
    is only considered if overload resolution would otherwise be
    ambiguous. I'm reading '14.5.5.2 for the third time now in this
    thread, and I'm gradually starting to understand what it is
    saying. Basically, for each function template, the compiler
    generates a unique imaginary argument for each template
    parameter, and considers the resulting instantiation. If type
    deduction for another function template succeeds with this
    instance, then the function template in question is at least as
    specialized as the function template for which type deduction
    succeeded. This is an ordering relationship, which could be
    symbolized by <=; i.e. for function templates x, y, x <= y IFF x
    is at least as specialized as y. (Note that this ordering can
    be established between any two function templates, regardless of
    name or parameters, but it is only used in overload resolution,
    which only concerns function templates with the same name.) In
    overload resolution, if the call is otherwise ambiguous, and x
    <= y, but !( y <= x ) (i.e. x < y), then overload resolution
    chooses x.

    The ordering is partial, and in this case, we have neither foo/1
    <= foo/2 nor foo/2 <= foo/1. If the compiler instantiates foo/1
    with some arbitrary, imaginary, non pointer type, type deduction
    fails for foo/2, and if the compiler instantiates foo/2 with two
    different imaginary T1 and T2, type deduction fails for foo/1.
    So the two foo are unordered.

    Note how this is different from:

    template<typename T>
    void foo(T,T){}

    template<typename T>
    void foo(T*,T*){}

    int main( ) {
    foo((int*)0,(int*)0);
    }

    In this case, too, both foo are "exact match" once type
    deduction has occured. But in this case, foo/2 is unambiguously
    more specialized than foo/1; if foo/2 is instantiated with some
    imaginary type T, type deduction works for foo/1, but if foo/1
    is instantiated with some imaginary (non-pointer) type T,
    type deduction fails for foo/2.

    Again, this ordering is over the function templates themselves,
    independant of any instantiations.

    (I'm sorry if I'm over explaining things here, but trying to
    explain it in such detail is helping me to understand it.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientie objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34



    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    James Kanze, Aug 2, 2007
    #13
  14. James Kanze <> wrote:
    > On Aug 1, 7:18 am, Craig Scott <> wrote:
    > > On Aug 1, 2:19 am, hurcan solter <> wrote:

    >
    > > > template<typename T>
    > > > void foo(T,T){}

    >
    > > > template<typename T1,typename T2>
    > > > void foo(T1*,T2*){}

    >
    > > > int main( ) {
    > > > foo((int*)0,(int*)0);
    > > > }

    >
    > [...]
    >
    > In this case. If the choice were between:
    > template< typename T >
    > void foo( T, T ) ;
    > and
    > template< typename T >
    > void foo( T*, T* ) ;
    > however, there is a partial ordering of template
    > "specializations" which comes into play [...]


    Does it? Are these template specializations?
    I thought they are overloaded function
    templates.

    Schobi

    --
    is never read
    I'm HSchober at gmx dot de
    "If there were some arcane way to remove the heads of every
    newsgroup troll on the planet, I think it would elevate
    humans to a whole new level of intelligence."
    Rocky Frisco



    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    Hendrik Schober, Aug 2, 2007
    #14

  15. > > In this case. If the choice were between:
    > > template< typename T >
    > > void foo( T, T ) ;
    > > and
    > > template< typename T >
    > > void foo( T*, T* ) ;
    > > however, there is a partial ordering of template
    > > "specializations" which comes into play [...]

    >
    > Does it? Are these template specializations?
    > I thought they are overloaded function
    > templates.
    >
    > Schobi
    >
    > --

    well they are not "specializations" per se but one is more
    "specialized" than the other as the word is used by standard.
    Same situation applies for the template specializations anyway,For
    example;

    template<typename T1,typename T2>
    class Foo{};

    template<typename T>
    class Foo<T,T>{};

    template<typename T1,typename T2>
    class Foo<T1*,T2*>{};


    int main()
    {
    Foo<int*,int*> zz;

    }
    Here, the instantiation is ambiguous again.the same resolution rules
    apply .

    @kanze
    Thanks very much for your attempts at explaining the situation,and
    your hint at formal ordering helped me found an excellent treatise of
    the subject in Mr.Vandevoorde's book in section 12.2 which explains
    why there is no ordering between the two templates that cleared it up
    for me. I think i was stuck at the idea that the argument and
    parameter pairs compared against their corresponding pairs in the
    parameter list entirely , but the truth,as it is always, ia different
    than what I've thought..


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    hurcan solter, Aug 3, 2007
    #15
  16. Victor Bazarov

    James Kanze Guest

    On Aug 2, 7:29 pm, "Hendrik Schober" <> wrote:
    > James Kanze <> wrote:
    > > On Aug 1, 7:18 am, Craig Scott <> wrote:
    > > > On Aug 1, 2:19 am, hurcan solter <> wrote:


    > > > > template<typename T>
    > > > > void foo(T,T){}


    > > > > template<typename T1,typename T2>
    > > > > void foo(T1*,T2*){}


    > > > > int main( ) {
    > > > > foo((int*)0,(int*)0);
    > > > > }


    > > [...]


    > > In this case. If the choice were between:
    > > template< typename T >
    > > void foo( T, T ) ;
    > > and
    > > template< typename T >
    > > void foo( T*, T* ) ;
    > > however, there is a partial ordering of template
    > > "specializations" which comes into play [...]


    > Does it? Are these template specializations?
    > I thought they are overloaded function
    > templates.


    That is extremely poorly expressed on my part. The partial
    ordering is over the function templates themselves, not over
    their specializations. Basically, here, after type deduction,
    we have two functions which are exact matches. Both are
    specializations of function templates, so the compiler attempts
    to use this partial ordering to resolve the overloading. In
    this case, it fails, because there is no ordering between these
    two function templates, but in principal, when there is ordering
    between the two function templates (not the specializations),
    then the "more specialized" is chosen.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientie objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34



    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    James Kanze, Aug 3, 2007
    #16
  17. Victor Bazarov

    Jerry Coffin Guest

    In article <>,
    says...
    > given the code snippet;
    >
    > template<typename T>
    > void foo(T,T){}
    >
    > template<typename T1,typename T2>
    > void foo(T1*,T2*){}
    >
    > int main( ) {
    >
    > foo((int*)0,(int*)0);
    >
    > }
    >
    > Could anyone please explain me why the second template is not more
    > viable for overload resolution?


    $14.5.5.2/3:
    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.

    So, in the first case, T becomes "int *". In the second case, T1 and T2
    both become "int". The result is two candidate functions, each of which
    takes two parameters, both of type "int *".

    $14.5.5.2/4, 5:
    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).

    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.

    The parameters you're passing are an exact match for the tranformed
    parameter lists of both functions. Neither template is more specialized
    than the other so the call is ambiguous.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
     
    Jerry Coffin, Aug 6, 2007
    #17
  18. Victor Bazarov

    Greg Herlihy Guest

    On 8/5/07 6:32 PM, in article ,
    "Jerry Coffin" <> wrote:

    > In article <>,
    > says...
    >> given the code snippet;
    >>
    >> template<typename T>
    >> void foo(T,T){}
    >>
    >> template<typename T1,typename T2>
    >> void foo(T1*,T2*){}
    >>
    >> int main( ) {
    >>
    >> foo((int*)0,(int*)0);
    >>
    >> }
    >>
    >> Could anyone please explain me why the second template is not more
    >> viable for overload resolution?

    >
    > $14.5.5.2/3:
    > 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.
    >
    > So, in the first case, T becomes "int *". In the second case, T1 and T2
    > both become "int". The result is two candidate functions, each of which
    > takes two parameters, both of type "int *".


    No, the paragraph cited from the Standard is describing how two, overloaded
    function templates may be "partially-ordered" in relation to one another.
    And since a partial ordering describes a relationship strictly between the
    function templates themselves - a partial ordering never varies. Therefore
    the types of arguments passed in the function call requiring overload
    resolution - is irrelevant to the process of determining whether a partial
    ordering exists between a pair of function templates. In other words, it is
    possible to determine whether any two, overloaded function templates are
    partially ordered in relation to each other - simply by performing the
    comparison described by the Standard.

    Furthermore, since the paragraph instructs us to "synthesize" a type - we
    are free to come up with any type that we like. And because we are looking
    for a type (or set of types) that will be a match for one foo() but not the
    other, choosing "int *" as our synthesized type - is not a very good choice.
    foo( int *, int *) is a match for either foo function template - so int * is
    not the kind of synthesized type that we should be looking for.

    Now, if we synthesize an "int" type instead - we are in business. Because a
    foo with two int parameters like so:

    foo( int, int )

    is a match for:

    foo( T, T )

    but not a match for:

    foo( T1 *, T2 * )

    - because an "int" (of course) is not any kind of pointer type.

    So at this point it appears that the foo( T1*, T2*) is the more specialized
    function template - unless we can synthesize type arguments that would match
    in the opposite manner. Can we do so? As it turns out, yes, we can. We can
    synthesize a foo with two different pointer types as parameters - like so:

    foo( int *, long *)

    is a match for;

    foo( T1 *, T2 *)

    but not match a match for:

    foo( T, T )

    Because, of course, int * and long * are not the same type.

    Therefore, since we were able to come up with one set of type arguments that
    matched only one of the foo template functions but not the other ( and found
    another set of types with the opposite matching behavior), we conclude that
    neither foo function template is more specialized than the other. So with no
    partial ordering to select one foo over the the other - the call is
    ambiguous.

    It is also worth point out - as James did earlier - that if foo( T, T ) were
    replaced with foo( T1, T2 ) - then a partial ordering would exist between
    the two foo() function templates.

    Greg
     
    Greg Herlihy, Aug 6, 2007
    #18
    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,861
    Eph0nk
    Oct 23, 2003
  2. =?Utf-8?B?Q2FpbGlu?=
    Replies:
    0
    Views:
    1,593
    =?Utf-8?B?Q2FpbGlu?=
    Sep 9, 2005
  3. Wolfgang Jeltsch

    overload resolution

    Wolfgang Jeltsch, Aug 31, 2003, in forum: C++
    Replies:
    2
    Views:
    405
    Filipe Sousa
    Aug 31, 2003
  4. Piotre Ugrumov
    Replies:
    3
    Views:
    374
    Nick Hounsome
    Jan 25, 2004
  5. Ying-Chieh Liao

    function overload (not operator overload)

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

Share This Page