Home > Software design >  Heterogenous vectors of pointers. How to call functions
Heterogenous vectors of pointers. How to call functions

Time:11-13

I would like to create a heterogeneous structure to store pointers to some classes so that I can loop through it and call a write() function.

The idea is this:

#include <boost/variant.hpp>
#include <vector>

template< typename T>
class A
{
    public:
        A(){}
        ~A(){}

        void write();

    private:
        T data;
};

template< typename T>
void A<T>::write()
{
    std::cout << data << std::endl;
}

int main()
{
   A<int> one;
   A<double> two;

   typedef boost::variant<A<int>*, A<double>* > registry;
   std::vector<registry> v;


   v.push_back(&one);
   v.push_back(&two);

   for(unsigned int i =0; i< v.size(); i  )
   {
       v[i]->write();
   }

}

However, this code does not compile. Showing the error:

error: base operand of ‘->’ has non-pointer type ‘__gnu_cxx::__alloc_traits<std::allocator<boost::variant<A<int>*, A<double>*> > >::value_type {aka boost::variant<A<int>*, A<double>*>}’
         v[i]->write();

How can I fix this? I would also appreciate ideas on the implementation

CodePudding user response:

v[i] returns a boost::variant<A<int>*, A<double>*> instead of a pointer to an instance of A, so you cannot use operator-> on it. You need to use boost::apply_visitor to visit the content fo the variant.

for(unsigned int i = 0; i < v.size(); i  ) {
  boost::apply_visitor([](auto a) { a->write(); }, v[i]);
}

Demo.

Since lambda uses auto as a parameter type is a feature of C 14, in C 11, you need to create a callable class with a template operator() as the visitor, as shown below:

struct Visitor {
  using result_type = void;
  template<typename T>
  result_type operator()(A<T>* a) const { a->write(); }
};

for(unsigned int i = 0; i < v.size(); i  ) {
  boost::apply_visitor(Visitor{}, v[i]);
}

Demo.

CodePudding user response:

Based on the previous answer I built:

class myVisitor
: public boost::static_visitor<>
{
    public:
        template< typename T>
        void operator() (A<T>* a) const
        {
            a->write();
        }
};

And use it in the code as:

for(auto x: v)
{
    boost::apply_visitor(myVisitor(), x);
}

What do you think?

  • Related