Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Which function should get chosen

Reply
Thread Tools

Which function should get chosen

 
 
Kaba
Guest
Posts: n/a
 
      08-06-2009
Hi,

In the following is a short code snippet concerning the overload
resolution with function templates. Which function should be chosen in
this case (i.e. what should the program return)?

template <typename Type>
class Base {};

template <typename Type>
class A : public Base<Type> {};

template <typename Type>
int f(const Base<Type>& that) {return 0;}

template <typename Type>
int f(const Type& that) {return 1;}

int main()
{
A<int> a;
return f(a);
}

I am surprised to see that both Visual Studio 2008 and Comeau C++ both
choose the unrestricted template (return 1). I'd argue that the other
one containing Base<Type> parameter is more specialized. What is going
on?

--
http://kaba.hilvi.org
 
Reply With Quote
 
 
 
 
Greg Herlihy
Guest
Posts: n/a
 
      08-06-2009
On Aug 6, 11:53*am, Kaba <(E-Mail Removed)> wrote:
>
> In the following is a short code snippet concerning the overload
> resolution with function templates. Which function should be chosen in
> this case (i.e. what should the program return)?
>
> template <typename Type>
> class Base {};
>
> template <typename Type>
> class A : public Base<Type> {};
>
> template <typename Type>
> int f(const Base<Type>& that) {return 0;}
>
> template <typename Type>
> int f(const Type& that) {return 1;}
>
> int main()
> {
> * * A<int> a;
> * * return f(a);
> }
>
> I am surprised to see that both Visual Studio 2008 and Comeau C++ both
> choose the unrestricted template (return 1). I'd argue that the other
> one containing Base<Type> parameter is more specialized. What is going
> on?


The compiler does not even consider the function template with the
Base<Type> parameter, because a call to that function would require
converting the argument to a base class template-id (specifically,
converting the A<int> argument to a B<int> parameter).

Now, according to §14.8.2.1/3, this type of conversion is allowed:

"If P is a class, and P has the form template-id, then A can be a
derived class of the deduced A."

There is however one significant restriction:

"These alternatives are considered only if type deduction would
otherwise fail."

Since there is another f() function template for which type deduction
does succeed - the compiler does even consider the other f() overload
when resolving the f() function call.

Greg



 
Reply With Quote
 
 
 
 
Kaba
Guest
Posts: n/a
 
      08-06-2009
Greg Herlihy wrote:
> "If P is a class, and P has the form template-id, then A can be a
> derived class of the deduced A."
>
> "These alternatives are considered only if type deduction would
> otherwise fail."


Thank you. I then have a related problem. I would like the following to
compile. However, the 0 is ambiguated because it can also be converted
to the null pointer:

template <typename Type>
class Base {};

template <typename Type>
class A
{
public:
A() {}
explicit A(const Type& that) {}
explicit A(const Type* that) {}

template <typename ThatType>
explicit A(const Base<ThatType>& that) {}
};

int main()
{
A<float> a(0);
return 0;
}

I do not want to use a cast to disambiguate in the constructor call.
Ideally, of course, the 0 shouldn't denote a null-pointer value but
there should be a special symbol for it: but's that's history. How do I
get around this?

This gives a context for the first post: I tried to use a template to
catch the type of the parameter. But that broke the Base constructor.

--
http://kaba.hilvi.org
 
Reply With Quote
 
Kaba
Guest
Posts: n/a
 
      08-06-2009
Kaba wrote:
> template <typename ThatType>
> explicit A(const Base<ThatType>& that) {}


Sorry, this constructor should have been implicit:

template <typename ThatType>
A(const Base<ThatType>& that) {}

--
http://kaba.hilvi.org
 
Reply With Quote
 
Kaba
Guest
Posts: n/a
 
      08-06-2009
Kaba wrote:

Ok, I was missing some more stuff. This should be a complete test case
for what I want to achieve. The constructors for which I pass a number
should run the A(const Type& that) constructor.

template <typename Type>
class Base {};

template <typename Type>
class C : public Base<Type> {};

template <typename Type>
class A
{
public:
A() {}
explicit A(const Type& that) {}
explicit A(const Type* that) {}

template <typename ThatType>
A(const Base<ThatType>& that) {}
};

int main()
{
C<float> a;
A<float> b(a);
A<float> c(0);
A<float> d(0.0);

A<int> e(0);
A<int> f(0.0);

return 0;
}

--
http://kaba.hilvi.org
 
Reply With Quote
 
Kaba
Guest
Posts: n/a
 
      08-06-2009
Kaba wrote:
> Kaba wrote:
>
> Ok, I was missing some more stuff. This should be a complete test case
> for what I want to achieve. The constructors for which I pass a number
> should run the A(const Type& that) constructor.


Solved it!:

http://kaba.hilvi.org/Programming_C+...ll_Pointer.htm

Let me know if you have a better technique in mind.

--
http://kaba.hilvi.org
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-07-2009
On Aug 6, 9:24 pm, Greg Herlihy <(E-Mail Removed)> wrote:
> On Aug 6, 11:53 am, Kaba <(E-Mail Removed)> wrote:
> > In the following is a short code snippet concerning the
> > overload resolution with function templates. Which function
> > should be chosen in this case (i.e. what should the program
> > return)?


> > template <typename Type>
> > class Base {};


> > template <typename Type>
> > class A : public Base<Type> {};


> > template <typename Type>
> > int f(const Base<Type>& that) {return 0;}


> > template <typename Type>
> > int f(const Type& that) {return 1;}


> > int main()
> > {
> > A<int> a;
> > return f(a);
> > }


> > I am surprised to see that both Visual Studio 2008 and
> > Comeau C++ both choose the unrestricted template (return 1).
> > I'd argue that the other one containing Base<Type> parameter
> > is more specialized. What is going on?


> The compiler does not even consider the function template with
> the Base<Type> parameter, because a call to that function
> would require converting the argument to a base class
> template-id (specifically, converting the A<int> argument to a
> B<int> parameter).


> Now, according to §14.8.2.1/3, this type of conversion is allowed:


> "If P is a class, and P has the form template-id, then A can
> be a derived class of the deduced A."


> There is however one significant restriction:


> "These alternatives are considered only if type deduction
> would otherwise fail."


> Since there is another f() function template for which type
> deduction does succeed - the compiler does even consider the
> other f() overload when resolving the f() function call.


I don't think that's right. The compiler applies type deduction
to both function templates, deducing Type == int for the first,
and Type == A<int> for the second. It then applies overload
resolution on the resulting functions: f( Base<int> const& )
(from the first template) and f( A< int > const& ) (from the
second template). Since the latter is a better match, it is
chosen. The choice of the "more specialize" is only used as a
tie breaker, if there would otherwise be ambiguity. That's not
the case here.

--
James Kanze (GABI Software) email:(E-Mail Removed)
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
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-07-2009
On Aug 6, 10:18 pm, Kaba <(E-Mail Removed)> wrote:
> Thank you. I then have a related problem. I would like the
> following to compile. However, the 0 is ambiguated because it
> can also be converted to the null pointer:


> template <typename Type>
> class Base {};


> template <typename Type>
> class A
> {
> public:
> A() {}
> explicit A(const Type& that) {}
> explicit A(const Type* that) {}


> template <typename ThatType>
> explicit A(const Base<ThatType>& that) {}
> };


> int main()
> {
> A<float> a(0);
> return 0;
> }


> I do not want to use a cast to disambiguate in the constructor
> call. Ideally, of course, the 0 shouldn't denote a
> null-pointer value but there should be a special symbol for
> it: but's that's history. How do I get around this?


Give the exact type. There's no other solution. In this case:
A<float> a( 0.0F ) ;

--
James Kanze (GABI Software) email:(E-Mail Removed)
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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
which route will be chosen ? Bart Cisco 1 05-22-2009 05:06 PM
CES 2006 Innovations Honorees Chosen Silverstrand Front Page News 0 11-16-2005 10:18 PM
strongest AP not being chosen silvus Wireless Networking 1 03-07-2005 09:40 PM
Media Player Won't Remember Which Skin is Chosen M Computer Support 3 02-03-2005 12:49 AM
write a function such that when ever i call this function in some other function .it should give me tha data type and value of calling function parameter komal C++ 6 01-25-2005 11:13 AM



Advertisments