Topic: partial ordering of template functions & parameter specification


Author: Marek Vondrak <none@none.com>
Date: Mon, 15 May 2006 09:45:08 -0500
Raw View
>> Hello.
>>
>> I have written the following program and am curious why it prints "1"
>> "2".
>> What are the exact effects of explicitly providing function template
>> parameters at the call? Is the second assign() function really a
>> specialization of the first assign() or is it an assign() overload?
>>
>> Thank you.
>> -- Marek
>>
>> -- cut --
>> #include <iostream>
>>
>> class O { };
>> class M { };
>>
>> template <class Left, class Right>
>> class Plus { };
>>
>> template <class Left, class Right, class Op>
>> int assign( Left & left, const Right & right, const Op & op )
>>     {
>>     return 1;
>>     }
>>
>> template <class Op>
>> int assign( M & left, const Plus<M, M> & right, const Op & op )
>>     {
>>     return 2;
>>     }
>>
>> int main()
>>     {
>>     M m;
>>
>>     std::cout << assign<M, Plus<M, M>, O>( m, Plus<M, M>(), O() ) <<
>> std::endl;
>>     std::cout << assign( m, Plus<M, M>(), O() ) << std::endl;
>>     }
>
> assign function templates are disparate function templates. There is no
> partial template specialization for functions.

Really? I think this was true in the prestandard era. Since C++98 there is a
partial specialization of functions and partional ordering rules.

> The first function
> template has three template arguments and the second has one. Therefore
> the second function template can not be used with three template
> arguments specified as you do.

Although I see the rationale behind your explanation, please consider the
following program.

class O { };
class M { };

template <class Left, class Right>
class Plus { };

// AS1
template <class Left, class Right, class Op>
void assign( Left & left, const Right & right, const Op & op ) { } //
Primary template

// AS2
template <>
void assign( M & left, const Plus<M, M> & right, const O & op ) { } //
Explicit specialization of AS1

int main()
    {
    M m;

    assign<M, Plus<M, M>, O>( m, Plus<M, M>(), O() ); // Calls AS2
    }

Why does it call AS2? It occurs to me, that AS1 is treated as the primary
template and AS2 as its explicit specialization. In the same sense I would
then believe that in the original program the first assign is the primary
template and the second assign its partial specialization:

template <class Left, class Right>
class Plus { };

// AS1
template <class Left, class Right, class Op>
void assign( Left & left, const Right & right, const Op & op ) { } //
Primary template again.

// AS2
template <class Op>
void assign( M & left, const Plus<M, M> & right, const Op & op ) { } //
Should be partial specialization of AS1?

int main()
    {
    M m;

    assign<M, Plus<M, M>, O>( m, Plus<M, M>(), O() ); // Calls AS1! Why?
This is inconsistent with the explicit specialization example!
    }

-- Marek



      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]