i am searching for a way to store different type of pointers in a map without using void* for obvious reasons. I actually know the types of the pointers at compile-time and these pointers as well as their types need to be const while their values need to be changed from times to times. The types are always some kind of numerical types.
Background: The variables behind these pointer are actually always global variables which need to changed if an specific event happens. Eachs event has an Id, the first member of that map, which changes the variable to a value transported by that event as a string.
So far i think boost::variant would do the trick. I am new to variant and i dont know whether the following would work as expected regarding the constness, but i assume after reading the f*cking manual that it should be ok. The main issue still is how to change that value behind that pointer utilising the standard conversions:
class Data{
public:
typedef boost::shared_ptr<Data> Ptr;
typedef boost::variant<double*, float*, unsigned int*, int*, unsigned short*, short*, unsigned char*, char*> PodPointerVariant;
double factor;
const PodPointerVariant varPointer;
Data(PodPointerVariant variable) :
factor(0.0),
varPointer(variable) {}
}
std::map<unsigned int, Data::Ptr> dataMap;
unsigned int intValue;
float floatValue;
void main()
{
intValue = 1;
Data::Ptr newEntry(new Data(&intValue));
newEntry->factor = 1.1;
dataMap->insert(std::make_pair(1,newEntry));
// Omitted find key and safety if not found...
unsigned int eventId = 1;
*(dataMap[eventId]->varPointer) = 2.1 * dataMap[1]->factor; // Should be automagically converted to 2 because the pointer is of type unsigned int, but gives a compiler error? I cant dereference that normally.
}
Is there an easy way to dereference like this? Maybe using a visitor class? Or anything else? Ideally Data->varPointer shall only be initialised once and only the value may be changed, like a "double * const", so i gets checked at compiled-time if somebody messes around with that pointer.
Thank you!
UPDATE
After some trial and error i found out that it indeed works as expected. This is what i've done this far:
template<typename U>
struct DeRefAssignVisitor : public boost::static_visitor<>
{
U x;
double factor;
DeRefAssignVisitor(U x, double factor) : x(x), factor(factor) { }
template <typename T>
void operator()(T* const p) const
{
*p = (T)(x * factor);
}
};
class Data{
public:
typedef boost::shared_ptr<Data> Ptr;
typedef boost::variant<double * const, float* const, unsigned long* const, long* const, unsigned short* const, short* const, unsigned char* const, char* const, plcbit* const> PodReferenceVariant;
double factor;
const PodPointerVariant varPointer;
Data(PodPointerVariant variable) :
factor(0.0),
varPointer(variable) {}
template <typename T>
void setPointerValue(T value) { boost::apply_visitor(DeRefAssignVisitor<T>(value, this->factor), this->varPointer); }
}
std::map<unsigned int, Data::Ptr> dataMap;
unsigned int intValue;
float floatValue;
void main()
{
intValue = 1;
floatValue = 2.111;
Data::Ptr newEntry(new Data(&intValue));
newEntry->factor = 1.1;
dataMap->insert(std::make_pair(1,newEntry));
// Omitted find key and safety if not found...
unsigned int eventId = 1;
dataMap[eventId]->setPointerValue(floatValue); // Works like a charme: converting compatible types automagically :-)
}
Templates 4TW :-D Thanks everybody!
Actually you can use visitors from boost.
And then