Kolyunya
Kolyunya

Reputation: 6230

C++ Operating with template objects

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

Answers (2)

ForEveR
ForEveR

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

Mike Seymour
Mike Seymour

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

Related Questions