metaprogramming solution to recursive function typedef ?

R

Roshan Naik

typedef int foo ( foo ); // foo is a pointer-to-function type that takes
another foo as argument and returns an int

I need to achieve the above effect somehow. This is not accepted by any
compiler I have tried, even though I cant spot anything in the standard that
restricts it.

Is there a way to achieve this typedefintion using metaprogramming ? I
noticed that boost::variant does some metaprogramming tricks to allow

variants to be contained in variants. But it is unclear to me how that is
acheived, also that problem _may_ not be exactly the same as this.

-Roshan Naik
 
K

Kai-Uwe Bux

Roshan said:
typedef int foo ( foo ); // foo is a pointer-to-function type that takes
another foo as argument and returns an int

I need to achieve the above effect somehow.

What is the real underlying problem that you are trying to solve?

[snip]


Best

Kai-Uwe Bux
 
A

Alf P. Steinbach

* Roshan Naik:
typedef int foo ( foo ); // foo is a pointer-to-function type that takes
another foo as argument and returns an int

I need to achieve the above effect somehow.

struct Foo
{
virtual int operator()( Foo const* ) const = 0;
};

Then if you need to pass such functors by value, you can wrap them in a
functor with a smart-pointer to the actual functor.
 
G

Greg

Roshan said:
typedef int foo ( foo ); // foo is a pointer-to-function type that takes
another foo as argument and returns an int

I need to achieve the above effect somehow. This is not accepted by any
compiler I have tried, even though I cant spot anything in the standard that
restricts it.

Is there a way to achieve this typedefintion using metaprogramming ? I
noticed that boost::variant does some metaprogramming tricks to allow

variants to be contained in variants. But it is unclear to me how that is
acheived, also that problem _may_ not be exactly the same as this.

Perhaps you want something along these lines:

template <class T>
struct CallFunctionPtr
{
typedef int (*functionPtr)(T);

typedef CallFunctionPtr<fPtr> next;
};

int main()
{
CallFunctionPtr<int(*)()>::next::functionPtr fPtr;

// fPtr is of type int (*)(int (*)())

CallFunctionPtr<int(*)()>::next::next:::functionPtr f2Ptr;

// f2Ptr is of type int (*)(int (*)(int (*)()))
}

Each "next" inner type corresponds to a function call to a function
whose pointer is being passed as a parameter. The number of "next"'s
that are chained together equals how many functions will be called
before the nested function pointers are exhausted.

Greg
 
P

Pete Becker

Roshan said:
typedef int foo ( foo ); // foo is a pointer-to-function type that takes
another foo as argument and returns an int

The comment is incorrect, for two reasons. First, foo is not defined,
because this is not a valid declaration. But you knew that. <g>

Second, if the argument type were changed from foo to, say, int, then
foo would not be a pointer to function type. It would be a function type.
 
R

Roshan Naik

Alf P. Steinbach said:
struct Foo
{
virtual int operator()( Foo const* ) const = 0;
};

Then if you need to pass such functors by value, you can wrap them in a
functor with a smart-pointer to the actual functor.

Thanks. But I already considered that and i need to have a real function
type. So i can use more
terse syntax like this...

int myFunc1 ( foo arg) {
//. ..
}

instead of having to write classes deriving from Foo and then implementing
( ) as a member function.

-Roshan
 
D

Dan Cernat

Roshan said:
typedef int foo ( foo ); // foo is a pointer-to-function type that takes
another foo as argument and returns an int
<snip>

so foo is
a pointer to a function that has as a sole argument
a pointer to a function that has as a sole argument
a pointer to a function that has as a sole argument
.....

/dan
 
R

Roshan Naik

Pete Becker said:
The comment is incorrect, for two reasons. First, foo is not defined,
because this is not a valid declaration. But you knew that. <g>

Please elaborate. I assume that the above declaration (if it would be
accpeted by any compiler)
would be equivalent to.....
typedef int (*foo) (foo);

Note that I can use A* within the declaration of class A. Thus foo here
doesnt have to be defined as its a pointer type (my way of thinking).
Second, if the argument type were changed from foo to, say, int, then
foo would not be a pointer to function type. It would be a function type.

Is there such a thing as "function type" for variables in C++ ? It is my
understanding that you can only
have a pointers/references to functions. There is no way to define a
value-type variable that holds a function.
You can only declare a pointer-type variable that stores the address of a
function.

A function itself has a "function type" but from the standpoint of declaring
a variable/parameter
we have to use pointer to function types.

-Roshan
 
P

Pete Becker

Roshan said:
A function itself has a "function type" but from the standpoint of declaring
a variable/parameter
we have to use pointer to function types.

In C that is correct. In C++ you can also create a reference to function
type, although that's of minor utility. Nevertheless, in both C and C++,
typedef int foo(int); defines a function type, not a pointer to function
type. To define a pointer to function type you need a *, which says
'pointer'.
 
R

Roshan Naik

In C that is correct. In C++ you can also create a reference to function
type, although that's of minor utility. Nevertheless, in both C and C++,
typedef int foo(int); defines a function type, not a pointer to function
type. To define a pointer to function type you need a *, which says
'pointer'.

And of what use is a function type ?

-Roshan
 
P

Pete Becker

Roshan said:
And of what use is a function type ?

Well, you can declare a pointer to that type:

typedef int foo(int);
typedef foo *foo_ptr;

Of course, most people do that all in one declaration. In C it's pretty
much pointless. In C++, though, it can be used to define the signature
of a member operator() of a template:

template <class Ftype>
struct function
{
Ret operator()(T1&, T2&, ..., TN&);
};

There's a lot of mechanism missing from that definiton, obviously
(needed to split Ftype to figure out what Ret, T1, T2, etc. really are).
But it's essentially what TR1's function template looks like:

#include <functional>
#include <math.h>
using std::tr1::function;

typedef float ft(float);
function<ft> func(fsin);

now func(1.0) returns fsin(1.0).

func = fcos;

now func(1.0) returns fcos(1.0).
 
K

Kaz Kylheku

Roshan said:
typedef int foo ( foo ); // foo is a pointer-to-function type that takes
another foo as argument and returns an int

I need to achieve the above effect somehow. This is not accepted by any
compiler I have tried, even though I cant spot anything in the standard that
restricts it.

What restricts it is that scope of the identifier foo begins after the
declarator that introduces it.
Is there a way to achieve this typedefintion using metaprogramming ?

You have to use a type which allows for forward references. This means
you have to use a struct or class, like this. Let's do it in a C89
compatible way:

/* introduce incomplete type */
struct foo_struct;

/* foo_fun is a pointer to a function that takes a foo_struct */
typedef int (*foo_fun)(struct foo_struct);

/* and a foo struct contains a pointer to a foo_fun */
struct foo_struct {
foo_fun *fun;
}

/* here is a foo_fun compatible function */
int foo_fun_impl(struct foo_struct s)
{
struct foo_struct self = { foo_fun_impl };

if (s.fun != foo_fun_impl)
s.fun(self);
}
I
noticed that boost::variant does some metaprogramming tricks to allow

variants to be contained in variants. But it is unclear to me how that is
acheived, also that problem _may_ not be exactly the same as this.

There is nothing contained within anything here, because a function
cannot take a function as a parameter, nor can it return a function. So
a function's type cannot have a function type among any of its
constituents.

The above struct trick only overcomes the lexical difficulty, namely
the identifier being declared is not available within its declarator.
There is no semantic problem being overcome.

Suppose you had the following language extension:

typedef incomplete x;

allowing you to assert that x is some completely unspecified type,
which can be completed in any manner whatsoever, not limited to classes
or structures. This could be accompanied by special rules that would
let you write something like:

typedef x (*x)(x);

thereby completing the type x as a pointer to function that takes an x
value and returns an x value.
 
K

Kaz Kylheku

Roshan said:
typedef int foo ( foo ); // foo is a pointer-to-function type that takes
another foo as argument and returns an int

I need to achieve the above effect somehow. This is not accepted by any
compiler I have tried, even though I cant spot anything in the standard that
restricts it.

What restricts it is that scope of the identifier foo begins after the
declarator that introduces it.
Is there a way to achieve this typedefintion using metaprogramming ?

You have to use a type which allows for forward references. This means
you have to use a struct or class, like this. Let's do it in a C89
compatible way:

/* introduce incomplete type */
struct foo_struct;

/* foo_fun is a pointer to a function that takes a foo_struct */
typedef int (*foo_fun)(struct foo_struct);

/* and a foo struct contains a pointer to a foo_fun */
struct foo_struct {
foo_fun fun;
};

/* here is a foo_fun compatible function */
int foo_fun_impl(struct foo_struct s)
{
struct foo_struct self = { foo_fun_impl };

if (s.fun != foo_fun_impl)
s.fun(self);
}
I
noticed that boost::variant does some metaprogramming tricks to allow

variants to be contained in variants. But it is unclear to me how that is
acheived, also that problem _may_ not be exactly the same as this.

There is nothing contained within anything here, because a function
cannot take a function as a parameter, nor can it return a function. So
a function's type cannot have a function type among any of its
constituents.

The above struct trick only overcomes the lexical difficulty, namely
the identifier being declared is not available within its declarator.
There is no semantic problem being overcome.

Suppose you had the following language extension:

typedef incomplete x;

allowing you to assert that x is some completely unspecified type,
which can be completed in any manner whatsoever, not limited to classes
or structures. This could be accompanied by special rules that would
let you write something like:

typedef x (*x)(x);

thereby completing the type x as a pointer to function that takes an x
value and returns an x value.
 
R

Roshan Naik

Kaz Kylheku said:
You have to use a type which allows for forward references. This means
you have to use a struct or class, like this. Let's do it in a C89
compatible way:

/* introduce incomplete type */
struct foo_struct;

/* foo_fun is a pointer to a function that takes a foo_struct */
typedef int (*foo_fun)(struct foo_struct);

/* and a foo struct contains a pointer to a foo_fun */
struct foo_struct {
foo_fun *fun;
}

/* here is a foo_fun compatible function */
int foo_fun_impl(struct foo_struct s)
{
struct foo_struct self = { foo_fun_impl };

if (s.fun != foo_fun_impl)
s.fun(self);
}

I am familiar with that trick, but what it gives you is a function that
takes a (functor type) struct as parameter instead of a function pointer.
80% there ...but no quite 100%.

I was hoping to be able to do some magic with templates and type
calculations with them to by-pass the compiler
restriction( i cannot definitely say it is a language restriction). But my
attempts so far on finding a solution with metaprogramming have been
unsuccessful.

-Roshan
 
A

Alf P. Steinbach

* Roshan Naik:
Thanks. But I already considered that and i need to have a real function
type. So i can use more
terse syntax like this...

int myFunc1 ( foo arg) {
//. ..
}

instead of having to write classes deriving from Foo and then implementing
( ) as a member function.

Pardon me for asking, but exactly what is it that you think prevents you from
writing simple functions and using them where Foo argument is expected?
 
R

Roshan Naik

Pardon me for asking, but exactly what is it that you think prevents you from
writing simple functions and using them where Foo argument is expected?

As I dont know what function will be actually called, until runtime.

int myFunc1 ( foo arg) { . .. }
int myFunc2 ( foo arg) { . .. }
int myFunc3 ( foo arg) { . .. }

myFunc1 ( myFunc2 ) ;
myFunc1 ( myFunc3 );

- Roshan Naik
 
A

Alf P. Steinbach

* Roshan Naik:
As I dont know what function will be actually called, until runtime.

int myFunc1 ( foo arg) { . .. }
int myFunc2 ( foo arg) { . .. }
int myFunc3 ( foo arg) { . .. }

myFunc1 ( myFunc2 ) ;
myFunc1 ( myFunc3 );

That doesn't make much sense to me as an argument against using a functor.
 
R

Roshan Naik

That doesn't make much sense to me as an argument against using a functor.

Consider the alternative to above code using functors:

struct myFunc1 : foo {
int operator( ) ( foo arg ) {
...
}
};

struct myFunc2 : foo {
int operator( ) ( foo arg ) {
...
}
};

struct myFunc3 : foo {
int operator( ) ( foo arg ) {
...
}
};

myFunc1 mf1;
myFunc2 mf2;
myFunc3 mf3;

mf1 ( mf2 ) ;
mf1 ( mf3 );


- Roshan Naik
 
A

Alf P. Steinbach

* Roshan Naik:
Consider the alternative to above code using functors:

struct myFunc1 : foo {
int operator( ) ( foo arg ) {
...
}
};

struct myFunc2 : foo {
int operator( ) ( foo arg ) {
...
}
};

struct myFunc3 : foo {
int operator( ) ( foo arg ) {
...
}
};

myFunc1 mf1;
myFunc2 mf2;
myFunc3 mf3;

mf1 ( mf2 ) ;
mf1 ( mf3 );

That makes, if possible, even less sense.

Where did you get the idea that the above is "the" alternative?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top