【问题标题】:Const Boost Variant with Pointer types in a map地图中带有指针类型的 Const Boost Variant
【发布时间】:2015-01-31 22:42:16
【问题描述】:

出于显而易见的原因,我正在寻找一种在不使用 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->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 :-D 谢谢大家!

【问题讨论】:

    标签: c++ pointers map boost-variant


    【解决方案1】:

    其实你可以使用 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);
    

    【讨论】:

    • 我虽然是这样,但我不知道如何为访问者添加参数,谢谢。我还假设这个简单的任务也可以模板化。我会试试看。
    • 感谢您指出正确的方向,我现在开始工作了!
    猜你喜欢
    • 1970-01-01
    • 2011-06-22
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 2021-07-25
    • 2020-03-20
    • 1970-01-01
    相关资源
    最近更新 更多