Sign in to follow this  
Dragon_Strike

if object has function call it

Recommended Posts

is it possible to have an if statement that says if object has function x call function x if (Object->Function) Object->Function(); shouldnt this be possible in compiler-time? just have the compiler check if the function name is defined...? im working in MS C++ visual studio 2005 PS. This is a possible solution to a problem i posted in another forum, but i dont think/hope it is counted as a cross post

Share this post


Link to post
Share on other sites
It is not pòssible to do that. To be able to write:

if (Object->Function)

Object has to have Function in order for the program to compile.

Explain to us what are you trying to accomplish. I'm sure there is a proper way to handle it.

Share this post


Link to post
Share on other sites
if (Object->Function)

was an example illustrating just about what im trying to do...

what i want to do is to create a class wrapper that takes a boost::any
and this wrapper has a function that calls a function that most of (but not all) the objects sent to boost::any has...

Share this post


Link to post
Share on other sites
Well, wouldn't you need to "cast" the boost::any to a specific type before calling the function, anyway? If that's the case, then you already know, at compile time, whether the type has the function or not. And if you're using templates, the compiler will break loudly at compile time if the function isn't found in the given type specified in the template.

Share this post


Link to post
Share on other sites
He wants to be able to do it at run time.

I personally think it's a bad idea, at least in c++.

In my mind, if I wanted to iterate a bunch of objects and call some function from them, they should have that function or inherit from a class that has it.

Share this post


Link to post
Share on other sites
Try this: Say you define a base class with the function you want to call as a pure virtual. Classes derive from this base class and define the function. I don't know about boost::any, but suppose you're passing a void pointer:

void CallingFunc(void *incoming)

use dynamic_cast to convert the void pointer to your base class:

BaseClass *ptr = dynamic_cast<BaseClass *>(incoming)

now you just need to check if ptr != NULL. If it's equal to NULL, then the incoming ptr wasn't derived from the BaseClass, and you can't call the function.

if(ptr) ptr->Func();

Share this post


Link to post
Share on other sites
Quote:
Original post by Numsgil
Try this: Say you define a base class with the function you want to call as a pure virtual. Classes derive from this base class and define the function. I don't know about boost::any, but suppose you're passing a void pointer:

void CallingFunc(void *incoming)

use dynamic_cast to convert the void pointer to your base class:

BaseClass *ptr = dynamic_cast<BaseClass *>(incoming)

now you just need to check if ptr != NULL. If it's equal to NULL, then the incoming ptr wasn't derived from the BaseClass, and you can't call the function.

if(ptr) ptr->Func();


I could be wrong, but I'm pretty sure that you can't dynamic_cast from a void* like that.

Quote:
C++ Standard 5.2.7.1
...
dynamic_cast<T>(v)
...
If T is a pointer type, v shall be an rvalue of a pointer to complete class type, and the result is an rvalue of type T.


Share this post


Link to post
Share on other sites
You can't dynamic cast. You could do this:

void CallIt(void* someObject, param...)
{
// don't call the method
}

void CallIt(Base* someObject, param...)
{
someObject->MyMethod(param...);
}

...
int a;
Derived b;
CallIt(&a,...);
CallIt(&b,...);

Share this post


Link to post
Share on other sites
Or you could change gears entirely and create some sort of event or signal/slot system where the objects that want a function called register it to the event. When this event happens, it calls all the registered functions.

A fairly nice way to handle this in C++ is to create a base class that behaves sort-of like a function:

class EventHandler
{
virtual void Call( /*some parameters*/ ) = 0;
MyEventHandler( GenericBaseClass instance )
{
//store instance somewhere
}
};


Then, you can create subclasses which overrides Call(). For actual registration of the event, you'd have an Event class that could store a list of EventHandlers and call Call() for each of them. Registering an EventHandler would consist of adding it to the Event's list. An object would register an EventHandler constructed with itself (the object, that is) as the c'tor's parameter.

But I get the feeling that Boost, like usual, has a class that does this for you. Anyone want to comment on this?

Well, the point of this is to change it from being "A bunch of things, some of which need to have X done on them" to "A bunch of things, which will make sure that X is done on them if they need it." This lets you treat the bunch of things all as generic things, and yet still have this function called when you need it.

<offtopic>And the secondary point is that if you had been using, say, C# or Python, this would have been a non-issue taking mere minutes to solve.</offtopic>

Share this post


Link to post
Share on other sites
Quote:
Original post by incin
You can't dynamic cast. You could do this:

void CallIt(void* someObject, param...)
{
// don't call the method
}

void CallIt(Base* someObject, param...)
{
someObject->MyMethod(param...);
}

...
int a;
Derived b;
CallIt(&a,...);
CallIt(&b,...);

unfortunately, that doesn't really help either. The OP won't know the type because it is contained in (presumably) a collection of boost::any's. Much as it pains me to admit an aussie's right [grin] Sc4Freak 's post is correct.

Share this post


Link to post
Share on other sites
If the name of the function is known at compile time, you can do this with template meta-programming and SFINAE. But it's ugly.

Let's say that you wanted to check for a member function named "foo", and call it if it exists in a particular class.


#include <iostream>

template<typename T>
struct has_foo_method
{
template <typename U, void (U::*)(void)>
struct sfinae { };

template <typename U, void (U::*)(void) const>
struct sfinae_const { };

typedef char small;
typedef char (&big)[2];

template<typename U> static small test(sfinae<U, &U::foo> *);
template<typename U> static small test(sfinae_const<U, &U::foo> *);
template<typename U> static big test(...);

static const bool value = sizeof test<T>(0) == sizeof(small);
};


template<typename T, bool CallIt>
struct call_foo
{
static void do_it(const T &) { }
static void do_it(T &) { }
};

template<typename T>
struct call_foo<T, true>
{
static void do_it(const T &obj) { obj.foo(); }
static void do_it(T &obj) { obj.foo(); }
};

template<typename T>
void call_foo_if_present(const T &obj)
{
const bool present = has_foo_method<T>::value;
call_foo<T, present>::do_it(obj);
}

template<typename T>
void call_foo_if_present(T &obj)
{
const bool present = has_foo_method<T>::value;
call_foo<T, present>::do_it(obj);
}

struct A
{
};

struct B
{
void foo() { std::cout << "foo!\n"; }
};

int main()
{
A a;
B b;

std::cout << "looking in an A...\n";
call_foo_if_present(a);

std::cout << "looking in a B...\n";
call_foo_if_present(b);

return 0;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this