By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
445,795 Members | 1,832 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 445,795 IT Pros & Developers. It's quick & easy.

Generic Pointer Type

P: n/a

For objects, we have "void*" as the generic pointer type. For instance:

enum ParamType { Int, Double };

void Func(void *const p,ParamType const pt)
{
switch (pt)
{
case Int: *(int*)p = 42; break;
case Double: *(double*)p = 42; break;
}
}

However, we're not so lucky when it comes to function pointer types. The
behaviour of the following snippet is undefined:

enum ParamType { Int, Double };

void Func(void *const p,ParamType const pt)
{
switch (pt)
{
case Int: ((void(*)(int))p)(42); break;
case Double: ((void(*)(double))p)(42); break;
}
}

I thought I might go about writing a class which would serve as a generic
function pointer. As this was just a pet project, I thought I'd make its
behaviour as well-defined as possible (to the extreme just for the craic!).
I'm designing the class in such a way that it should behave exactly like an
intrinsic function pointer type. I've also taken some liberties in writing
the code, e.g. the behaviour is undefined if you assign from an
uninitialised FuncPtr object. Here's what I've got at the moment:

#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <new>

class FuncPtr {
private:

std::size_t quant; /* Size in bytes of function pointer */
void *pbytes;

public:

FuncPtr() : pbytes() {}

template<class T>
FuncPtr(T const p) : quant(sizeof p)
{
pbytes = std::malloc(quant);
if (!pbytes) throw std::bad_alloc();

std::memcpy(pbytes,&p,quant);
}

FuncPtr(FuncPtr const &a) : quant(a.quant)
{
pbytes = std::malloc(quant);
if (!pbytes) throw std::bad_alloc();

std::memcpy(pbytes,a.pbytes,quant);
}

FuncPtr &operator=(FuncPtr const &a)
{
quant = a.quant;

pbytes = std::realloc(pbytes,quant);
if (!pbytes) throw std::bad_alloc();

std::memcpy(pbytes,a.pbytes,quant);

return *this;
}

~FuncPtr() { free(pbytes); }

template<class T>
operator T() const
{
return *(T*)pbytes;
}
};

enum ParamType { Int, Double };

void Foo(FuncPtr const p,ParamType const pt)
{
switch (pt)
{
case Int: ((void(*)(int))p)(5); break;
case Double: ((void(*)(double))p)(5); break;
}
}

#include <iostream>
#include <ostream>

void FuncI(int) { std::cout << "Int function called" << std::endl; }
void FuncD(double) { std::cout << "Double function called" << std::endl; }

int main()
{
FuncPtr a;
FuncPtr const b = FuncD;

a = b;

Foo(a,Double);

Foo(FuncI,Int);
}
I realise it's a bit much to use dynamic memory allocation, but it's sort
of the only way I could _guarantee_ the correct alignment and size (short
of playing around with unions and what have you).

Anywho I just thought I'd throw that out there to see what kind of
responses I get.

--

Frederick Gotham
Nov 6 '06 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Frederick Gotham:
template<class T>
operator T() const
{
return *(T*)pbytes;
}

That would be more politically correct as:

return *(T const*)pbytes;

(although it doesn't make a difference).

--

Frederick Gotham
Nov 6 '06 #2

P: n/a

Frederick Gotham wrote:
I thought I might go about writing a class which would serve as a generic
function pointer. As this was just a pet project, I thought I'd make its
behaviour as well-defined as possible (to the extreme just for the craic!).
I'm designing the class in such a way that it should behave exactly like an
intrinsic function pointer type. I've also taken some liberties in writing
the code, e.g. the behaviour is undefined if you assign from an
uninitialised FuncPtr object.
Not to rain on your parade man but boost has this already. Check out
the function library. It will be in the next C++ standard and works
with things like bind, lambda, and all the algorithms in the std lib.
It's a pretty good wheel. Your time might be spent better on something
else.

Nov 6 '06 #3

P: n/a

Noah Roberts wrote:
Frederick Gotham wrote:
I thought I might go about writing a class which would serve as a generic
function pointer. As this was just a pet project, I thought I'd make its
behaviour as well-defined as possible (to the extreme just for the craic!).
I'm designing the class in such a way that it should behave exactly like an
intrinsic function pointer type. I've also taken some liberties in writing
the code, e.g. the behaviour is undefined if you assign from an
uninitialised FuncPtr object.

Not to rain on your parade man but boost has this already. Check out
the function library. It will be in the next C++ standard and works
with things like bind, lambda, and all the algorithms in the std lib.
It's a pretty good wheel. Your time might be spent better on something
else.
Here's your original problem solved with boost::function:
#include <iostream>
#include <boost/any.hpp>

#include <boost/function.hpp>

void f1(int x) { std::cout << "void f1(int).\n"; }
void f2(double x) { std::cout << "void f2(double).\n"; }
int f3(double x) { std::cout << "int f3(double).\n"; return
static_cast<int>(x); }

void Func(boost::function<void (int)const & f)
{
f(42);
}

struct functor
{
void operator() (int x) { std::cout << "void functor::()(int).\n"; }
};

int main()
{
boost::function<void (int)f;

f = &f1;
Func(f);

f = &f2;
Func(f);

f = &f3;
Func(f);

Func(&f3);

functor fun;
Func(fun);

int y; std::cin >y;
return 0;
}

f can be assigned any invocable object that can be called with an int
as parameter and returns an object convertable to void. Func can be
used the same.

Nov 6 '06 #4

This discussion thread is closed

Replies have been disabled for this discussion.