Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   function pointer as template parameter + type deduction (http://www.velocityreviews.com/forums/t686980-function-pointer-as-template-parameter-type-deduction.html)

er 06-07-2009 01:23 AM

function pointer as template parameter + type deduction
 
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)?




er 06-07-2009 02:23 AM

Re: function pointer as template parameter + type deduction
 
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.

Alf P. Steinbach 06-07-2009 08:34 AM

Re: function pointer as template parameter + type deduction
 
* 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!

er 06-07-2009 03:30 PM

Re: function pointer as template parameter + type deduction
 
On Jun 7, 4:34*am, "Alf P. Steinbach" <al...@start.no> 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.

Bart van Ingen Schenau 06-08-2009 06:01 PM

Re: function pointer as template parameter + type deduction
 
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/


er 06-09-2009 02:04 AM

Re: function pointer as template parameter + type deduction
 
On Jun 8, 2:01*pm, Bart van Ingen Schenau <b...@ingen.ddns.info>
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.



All times are GMT. The time now is 07:04 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.