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]);
}
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]);
}
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?