In article <1110035461.848248.135370@o13g2000cwo.googlegroups .com>,
"Imre" <jrms@pager.hu> wrote:
[color=blue]
> Why is the function template a better match for the call in the
> following code?
>
> And how could I write a version of F() that should be called if the
> argument is a pointer to a type that is derived from B, while the
> template version should be called for all other argument types?
>
> #include <iostream>
>
> using namespace std;
>
> struct B {};
> struct D: public B {};
>
> template <typename T>
> int F(T &t) { return 1; }
> int F(B *pb) { return 2; }
>
> int main(int argc, char* argv[])
> {
> D *pd = new D;
> int i = F(pd);
> cout << i << '\n'; // writes 1 (VC++ 7.1), I'd like to get 2
> return 0;
> }[/color]
The template is a better match because:
int F<D*>(D*&);
is a better match for a D* argument than:
int F(B*);
(no conversion from D* to B* required for the former.
If you have access to the incredibly useful utilities enable_if and
is_convertible (maybe look at
www.boost.org) you could do something like
the listing below. I'm using Metrowerks which has these facilities
built in, and spells enable_if as restrict_to, and that's what I'm
posting so that I can post tested code:
#include <iostream>
using namespace std;
struct B {};
struct D: public B {};
template <typename T>
typename Metrowerks::restrict_to
<
!Metrowerks::is_convertible<T, B*>::value,
int[color=blue]
>::type[/color]
F(T &t) { return 1; }
int F(B *pb) { return 2; }
int main(int argc, char* argv[])
{
D *pd = new D;
int i = F(pd);
cout << i << '\n'; // writes 2 for me
return 0;
}
-Howard