Topic: Template argument deduction confusion
Author: Joel Hegg <joelhegg@acm.org>
Date: Tue, 31 Jul 2001 01:28:01 GMT Raw View
I have some code that uses templates and method pointers. I've been
trying to use template deduction to clean some of it up, but the compiler
is giving me all sorts of weird errors that have left me totally confused.
Stroustrup's coverage of template argument deduction is pretty light. Can
somebody explain to me what's going on with the example below? FWIW, I'm
using g++ 2.95.2.
Thanks,
Joel
class Foo
{
public:
void xyz() { }
};
class Bar: public Foo {};
template<typename Result> void do_nothing(Result (Bar::*Method)()) {}
template<typename T, typename Result> void do_nothing2(Result
(T::*Method)()) {}
void main()
{
// doesn't compile, compiler says:
// no matching function for call to `do_nothing (void (Foo::*)())'
// even though I explicity say xyz is a member of Bar
do_nothing(&Bar::xyz);
// compiles fine, for some reason specifying the return type
// gets rid of the Foo error.
do_nothing<void>(&Bar::xyz);
// compiles fine, for some reason leaving the class type
// free allows deduction to work properly
do_nothing2(&Bar::xyz);
}
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: richard@ex-parrot.com (Richard Smith)
Date: Tue, 31 Jul 2001 17:06:05 GMT Raw View
Joel Hegg <joelhegg@acm.org> wrote in message news:<Pine.GSO.4.31.0107301940130.14611-100000@ux12.cso.uiuc.edu>...
> class Foo
> {
> public:
> void xyz() { }
> };
>
> class Bar: public Foo {};
>
> template<typename Result> void do_nothing(Result (Bar::*Method)()) {}
> template<typename T, typename Result> void do_nothing2(Result
> (T::*Method)()) {}
>
> void main()
> {
> // doesn't compile, compiler says:
> // no matching function for call to `do_nothing (void (Foo::*)())'
> // even though I explicity say xyz is a member of Bar
> do_nothing(&Bar::xyz);
The problem is that &Bar::xyz has type "void (Foo::*)()" and needs to
be converted to type "void (Bar::*)()" before it can be passed to
do_nothing<void>, which would require an implicit pointer-to-member
conversion
[4.11]; however, "implicit conversions (clause 4) will only be
performed on a function argument ... if the parameter type contains no
template-parameters that participate in template argument deduction"
[14.8.1, para 4].
When you then tried,
> // compiles fine, for some reason specifying the return type
> // gets rid of the Foo error.
> do_nothing<void>(&Bar::xyz);
the template parameter is explicitly specified and so does the
function argument does not contain any template arguments that
participate in template argument deduction, and the implicit
conversion occurs. Your third example,
> // compiles fine, for some reason leaving the class type
> // free allows deduction to work properly
> do_nothing2(&Bar::xyz);
actually calls the function do_nothing<Foo, void>.
Richard Smith
---
[ 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.research.att.com/~austern/csc/faq.html ]
Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Tue, 31 Jul 2001 18:38:27 GMT Raw View
"Joel Hegg" <joelhegg@acm.org> wrote in message
news:Pine.GSO.4.31.0107301940130.14611-100000@ux12.cso.uiuc.edu...
> I have some code that uses templates and method pointers. I've been
> trying to use template deduction to clean some of it up, but the compiler
> is giving me all sorts of weird errors that have left me totally confused.
> Stroustrup's coverage of template argument deduction is pretty light. Can
> somebody explain to me what's going on with the example below? FWIW, I'm
> using g++ 2.95.2.
>
> class Foo
> {
> public:
> void xyz() { }
> };
>
> class Bar: public Foo {};
>
> template<typename Result> void do_nothing(Result (Bar::*Method)()) {}
> template<typename T, typename Result> void do_nothing2(Result
> (T::*Method)()) {}
>
> void main()
> {
> // doesn't compile, compiler says:
> // no matching function for call to `do_nothing (void (Foo::*)())'
> // even though I explicity say xyz is a member of Bar
> do_nothing(&Bar::xyz);
>
> // compiles fine, for some reason specifying the return type
> // gets rid of the Foo error.
> do_nothing<void>(&Bar::xyz);
>
> // compiles fine, for some reason leaving the class type
> // free allows deduction to work properly
> do_nothing2(&Bar::xyz);
> }
xyz() is a member of Foo, not Bar. Thus Bar::xyz refers to Foo::xyz. I
cannot find a reference to decide whether the type is thus permitted to be
void (Foo::*)(), or whether it is void (Bar::*)() because of the explicit
Bar:: gcc obviously chooses the Foo:: variety.
Given that choice, you don't have a pointer-to-member-function of Bar, so
template argument type deduction doesn't work for the return type alone, and
do_nothing(&Bar::xyz) doesn't work. However, if you specify the return type,
then the pointer-to-base-member-function to
pointer-to-derived-member-function implicit conversion kicks in, so
do_nothing<void>(&Bar::xyz) is fine.
If you leave the class type of the pointer-to-member-function as a template
parameter, then the compiler can deduce it to match the actual type supplied
(here the compiler will choose T==Foo, given its error message above)
Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer
---
[ 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.research.att.com/~austern/csc/faq.html ]