我正在寻找一种方法来在地图中存储不同类型的指针而不使用void *,原因很明显。我实际上知道编译时指针的类型,这些指针以及它们的类型需要是const,而它们的值需要随时更改。类型总是某种数字类型。
背景 这些指针后面的变量实际上是全局变量,如果发生特定事件,则需要更改这些变量。每个事件都有一个Id,即该映射的第一个成员,它将该变量更改为该事件作为字符串传输的值。
到目前为止,我认为boost :: variant可以解决问题。我是变形的新手,我不知道以下是否会对constness有所作为,但我在阅读f * cking手册之后我认为应该没问题。主要问题仍然是如何利用标准转换来改变该指针后面的值:
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.
}
这样有一种简单的解除引用方式吗?也许使用访客班?还是其他什么?理想情况下,Data-&gt; varPointer只能初始化一次,只有值可以改变,就像“double * const”一样,所以如果有人在那个指针上乱搞,我会在编译时检查。
谢谢!
更新
经过一些试验和错误后,我发现它确实按预期工作。这就是我迄今为止所做的:
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 :-)
}
模板4TW :-感谢大家!
答案 0 :(得分:2)
实际上你可以使用来自boost的访客。
class AssignVisitor : public boost::static_visitor<>
{
public:
double x;
AssignVisitor(double x) : x(x) { }
void operator()(int* p)
{
*p = (int)x;
}
void operator()(double* p)
{
*p = (double)x;
}
//and so on
};
然后
boost::apply_visitor(AssignVisitor(2.1 * dataMap[1]->factor), dataMap[eventId]->varPointer);