Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > function pointer as template parameter + type deduction

Reply
Thread Tools

function pointer as template parameter + type deduction

 
 
er
Guest
Posts: n/a
 
      06-07-2009
Hi,

here's a problem:

struct A{};

void f(const A&a){}

template<typename T,void (*)(const T&)>
void g(const T& t){}

template<typename T>
void g2(const T& t,void (*)(const T&)){}

A a;

g<f>(a); // (1)
g<A,f>(a); // (2)
g2(a,f); // (3)

(2) and (3) compile fine, not 1. Why exactly? Any suggestion to
approach (1)?



 
Reply With Quote
 
 
 
 
er
Guest
Posts: n/a
 
      06-07-2009
PS: g++ --version
i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490)
Copyright (C) 2005 Free Software Foundation, Inc.
 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      06-07-2009
* er:
> Hi,
>
> here's a problem:
>
> struct A{};
>
> void f(const A&a){}
>
> template<typename T,void (*)(const T&)>
> void g(const T& t){}


What's the point of the unnamed template parameter?

One suspects a case Evil Premature Optimization, that the intention is to shave
a (conjectured but quite possibly not even real) nano-second by calling some
routine "directly" instead of having it passed as a routine pointer argument.

EPO is unfortunately a root cause of so much extreme and unnecessary complexity.


> template<typename T>
> void g2(const T& t,void (*)(const T&)){}
>
> A a;
>
> g<f>(a); // (1)
> g<A,f>(a); // (2)
> g2(a,f); // (3)
>
> (2) and (3) compile fine, not 1. Why exactly?


You have defined g with two template parameters, one which is anonymous and
therefore cannot ever be deduced, hence must always be explicitly specified.


> Any suggestion to approach (1)?


Don't.

You're into the second root cause of extreme and unnecessary complexity, namely
the Elegant Notation Fetish (ENF), where almost any absurdly huge baggage of
cryptic, complex, counter-intuitive code is deemed acceptable to shave /one/
character, or perhaps two, in a single very unimportant expression somewhere.

But if you strongly feel that providing the type parameter is very un-elegant,
that it simply must be deduced from the specified function, then perhaps like

<code>
struct A{};
void f(const A&a){}

struct F
{
typedef A ArgType;
static void effect( ArgType const& a ) { ::f( a ); }
};

template< class Func >
void g( typename Func::ArgType const& t ) {}

int main()
{
A a;
g<F>(a);
}
</code>


Cheers & hth.,

- Alf

--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! Just going there is good. Linking
to it is even better! Thanks in advance!
 
Reply With Quote
 
er
Guest
Posts: n/a
 
      06-07-2009
On Jun 7, 4:34*am, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * er:
>
> > Hi,

>
> > here's a problem:

>
> > struct A{};

>
> > void f(const A&a){}

>
> > template<typename T,void (*)(const T&)>
> > void g(const T& t){}

>
> What's the point of the unnamed template parameter?
>
> One suspects a case Evil Premature Optimization, that the intention is to shave
> a (conjectured but quite possibly not even real) nano-second by calling some
> routine "directly" instead of having it passed as a routine pointer argument.
>
> EPO is unfortunately a root cause of so much extreme and unnecessary complexity.
>
> > template<typename T>
> > void g2(const T& t,void (*)(const T&)){}

>
> > * * A a;

>
> > * * g<f>(a); * * * // (1)
> > * * g<A,f>(a); * // (2)
> > * * g2(a,f); * * * *// (3)

>
> > (2) and (3) compile fine, not 1. Why exactly?

>
> You have defined g with two template parameters, one which is anonymous and
> therefore cannot ever be deduced, hence must always be explicitly specified.
>
> > *Any suggestion to approach (1)?

>
> Don't.
>
> You're into the second root cause of extreme and unnecessary complexity, namely
> the Elegant Notation Fetish (ENF), where almost any absurdly huge baggage of
> cryptic, complex, counter-intuitive code is deemed acceptable to shave /one/
> character, or perhaps two, in a single very unimportant expression somewhere.
>
> But if you strongly feel that providing the type parameter is very un-elegant,
> that it simply must be deduced from the specified function, then perhaps like
>
> <code>
> struct A{};
> void f(const A&a){}
>
> struct F
> {
> * * *typedef A ArgType;
> * * *static void effect( ArgType const& a ) { ::f( a ); }
>
> };
>
> template< class Func >
> void g( typename Func::ArgType const& t ) {}
>
> int main()
> {
> * * *A a;
> * * *g<F>(a);}
>
> </code>
>
> Cheers & hth.,
>
> - Alf
>
> --
> Due to hosting requirements I need visits to <url:http://alfps.izfree.com/>.
> No ads, and there is some C++ stuff! Just going there is good. Linking
> to it is even better! Thanks in advance!


Thanks. Your answer is not lost on me although it answers a different
question from the one I (vaguely) intended. Here's a corrected and
extended version:

struct A{};
struct B{};
void f1(const A&a){}
void f1(const B&b){}
void f2(const A&a){}
void f2(const B&b){}

template<typename T,void (*fun)(const T&)>
void g(const T& t){}

template<typename T>
void g2(const T& t,void (*fun)(const T&)){}

template<typename T,void (*fun)(const T&)>
struct fun_ptr{
static void call(const T& t){ return fun(t); }
};

template<typename T>
struct f1_ : fun_ptr<T,f1>{};
template<typename T>
struct f2_ : fun_ptr<T,f2>{};

template<template<typename> class F,typename T>
void g3(const T& t){
typedef F<T> fun_t;
return fun_t::call(t);
}

//g<f1>(a); //won't compile
g<A,f1>(a);
g2(a,f1);
g3<f1_>(a);


g3 does the job i.e. 1) function pointer passed as a template argument
2) T is deduced from arguments, but it requires an f_ for each f.
 
Reply With Quote
 
Bart van Ingen Schenau
Guest
Posts: n/a
 
      06-08-2009
er wrote:

> Thanks. Your answer is not lost on me although it answers a different
> question from the one I (vaguely) intended. Here's a corrected and
> extended version:
>
> struct A{};
> struct B{};
> void f1(const A&a){}
> void f1(const B&b){}
> void f2(const A&a){}
> void f2(const B&b){}
>
> template<typename T,void (*fun)(const T&)>
> void g(const T& t){}
>
> template<typename T>
> void g2(const T& t,void (*fun)(const T&)){}
>
> template<typename T,void (*fun)(const T&)>
> struct fun_ptr{
> static void call(const T& t){ return fun(t); }
> };
>
> template<typename T>
> struct f1_ : fun_ptr<T,f1>{};
> template<typename T>
> struct f2_ : fun_ptr<T,f2>{};
>
> template<template<typename> class F,typename T>
> void g3(const T& t){
> typedef F<T> fun_t;
> return fun_t::call(t);
> }
>
> //g<f1>(a); //won't compile
> g<A,f1>(a);
> g2(a,f1);
> g3<f1_>(a);
>
>
> g3 does the job i.e. 1) function pointer passed as a template argument
> 2) T is deduced from arguments, but it requires an f_ for each f.


There is a small, but very significant difference in the template
parameters of g() and g3(). Perhaps it becomes obvious if we put the two
declarations next to each other:
template<typename T,void (*fun)(const T&)> void g (const T& t);
template<template<typename> class F,typename T> void g3(const T& t);

As you can see, in g() the template parameter T comes first, but in
g3(), T comes last.
The problem is that any template arguments that you specify explicitly
are bound to the first N template parameters and only the remaining
(unspecified) parameters are used in the template argument deduction
based on the function-call arguments.
In the call 'g<f1>(a)', the specified argument 'f1' is bound to the
first template parameter (T) which fails because a type is expected
instead of a value.

Unfortunately, you are in a double bind here, because there is no way to
specify the template parameters of g() such that the call 'g<f1>(a)'
becomes well-formed.
Your best choice is to use the pattern of g2().

Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

 
Reply With Quote
 
er
Guest
Posts: n/a
 
      06-09-2009
On Jun 8, 2:01*pm, Bart van Ingen Schenau <(E-Mail Removed)>
wrote:
> er wrote:
> > Thanks. Your answer is not lost on me although it answers a different
> > question from the one I (vaguely) intended. Here's a corrected and
> > extended version:

>
> > struct A{};
> > struct B{};
> > void f1(const A&a){}
> > void f1(const B&b){}
> > void f2(const A&a){}
> > void f2(const B&b){}

>
> > template<typename T,void (*fun)(const T&)>
> > void g(const T& t){}

>
> > template<typename T>
> > void g2(const T& t,void (*fun)(const T&)){}

>
> > template<typename T,void (*fun)(const T&)>
> > struct fun_ptr{
> > * * static void call(const T& t){ return fun(t); }
> > };

>
> > template<typename T>
> > struct f1_ : fun_ptr<T,f1>{};
> > template<typename T>
> > struct f2_ : fun_ptr<T,f2>{};

>
> > template<template<typename> class F,typename T>
> > void g3(const T& t){
> > * * typedef F<T> fun_t;
> > * * return fun_t::call(t);
> > }

>
> > //g<f1>(a); //won't compile
> > g<A,f1>(a);
> > g2(a,f1);
> > g3<f1_>(a);

>
> > g3 does the job i.e. 1) function pointer passed as a template argument
> > 2) T is deduced from arguments, but it requires an f_ for each f.

>
> There is a small, but very significant difference in the template
> parameters of g() and g3(). Perhaps it becomes obvious if we put the two
> declarations next to each other:
> *template<typename T,void (*fun)(const T&)> * * *void g (const T& t);
> *template<template<typename> class F,typename T> void g3(const T& t);
>
> As you can see, in g() the template parameter T comes first, but in
> g3(), T comes last.
> The problem is that any template arguments that you specify explicitly
> are bound to the first N template parameters and only the remaining
> (unspecified) parameters are used in the template argument deduction
> based on the function-call arguments.


Thanks. I was hoping some non-trivial named parameters (as opposed to
positional) approach or a related pattern could break free of this
rule.

 
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
function template type deduction from default parameter tobias.loew@steag.com C++ 2 01-08-2013 07:53 AM
return type deduction for a function template C++Liliput C++ 2 10-24-2008 08:09 AM
template class instantiate without template parameter, automatic type deduction Fei Liu C++ 4 10-26-2007 02:39 PM
template class instantiate without template parameter, automatictype deduction Fei Liu C++ 0 10-25-2007 08:12 PM
Template parameter Deduction Neelesh C++ 4 11-10-2005 12:52 PM



Advertisments