Reputation: 6230
I've a class
class BarBase {
};
and a derived template class, which stores a pointer to a member function and a pointer to an object of the same class
template<typename TypeName> class Bar: public BarBase
{
void ( TypeName::*action ) ( void );
TypeName* object;
};
I create instances of Bar
and store pointers to them in the vector of another class Foo
class Foo {
private:
vector<BarBase*> myBars;
...
};
Now to the question. Foo has a template function
template <typename TypeName>
void Foo::foo( TypeName* object , void ( TypeName::*action ) ( void ) )
In this function how do I find in myBars
elements with fields object
and action
equal to parameters of this function? As you can see, I can not directly access the fields like this->myBars[i]->action
since these fields are not (and can not be) members of BarBase
.
EDIT
I do can compare object
. I add a virtual size_t getObject (){};
to BarBase
and override it in Bar
like virtual size_t getObject (){ return (size_t)this->object; };
. Then I compare two size_t
, but I do not know, how to convert action
to a number...
Upvotes: 4
Views: 199
Reputation: 55887
You can use something like this, if you don't want use Mike variant (i prefer his variant).
class BarBase
{
public:
virtual ~BarBase() { }
virtual void* getObject() { return 0; }
virtual const char* getFunctionName() { return 0; }
};
template<typename T>
class Bar : public BarBase
{
public:
Bar(T* obj, void (T::*func) (void)):object(obj), action(func)
{
}
virtual void* getObject() { return object; }
virtual const char* getFunctionName() { return typeid(action).name(); }
T* object;
void (T::*action)(void);
};
http://liveworkspace.org/code/d79e33d4597ee209645026b2100330f3
EDIT.
Sorry. It's not solution of problem, since typeid(&S::action).name()
may be equal to typeid(&S::other_action).name()
.
Also, you can use dynamic_cast
or static_cast
not for all objects in vector.
class BarBase
{
public:
virtual ~BarBase() { }
virtual void* getObject() const { return 0; }
};
template<typename T>
class Bar : public BarBase
{
public:
Bar(T* obj, void (T::*func) (void)):object(obj), action(func)
{
}
virtual void* getObject() const { return object; }
T* object;
void (T::*action)(void);
};
for (auto pos = objects.begin(); pos != objects.end(); ++pos)
{
if ((*pos)->getObject() == &p)
{
auto bar = static_cast<Bar<S>*>(*pos);
if (bar->action == act)
{
// right object founded.
}
}
}
http://liveworkspace.org/code/87473a94411997914906c22ef0c31ace
Upvotes: 1
Reputation: 254431
The simplest solution is to make the base class polymorphic, and use dynamic_cast
to determine whether it has the expected type:
class BarBase {
public:
virtual ~BarBase() {} // virtual function required for polymorphism
};
Bar<TypeName>* bar = dynamic_cast<Bar<TypeName>*>(myBars[i]);
if (bar && bar->object == object && bar->action == action) {
// it's a match
}
This does add some overhead to support RTTI; off the top of my head, I can't think of any well-defined way to do this that doesn't add overhead.
Upvotes: 2