简体   繁体   English

C ++:模板函数从联合检索值

[英]C++: template function to retrieve value from an union

I am writing a template to get value from a collection that can hold different data types. 我正在编写一个模板,以从可以容纳不同数据类型的集合中获取价值。 for ex a variant structure. 例如一个变体结构。 But i get a warning when the compiler generates code for assignments with other types. 但是,当编译器为其他类型的赋值生成代码时,我会收到警告。 for ex 对于前

struct Variant
{
    enum Type
    {
        _bool,
        _int
    };
    Type type;

    union VAL
    {
        bool bVal;
        int nVal;
    }val;
};

template <typename ValType>
void GetValue(Variant v, ValType val)
{
    if(v.type == Variant::_bool)
    {
        val = v.val.bVal;
    }
    else if(v.type == Variant::_int)
    {
        val = v.val.nVal; // C4800
    }
}

Variant v;
v.type = Variant::_bool;
v.val.bVal = true;

bool bVal(false);
GetValue(v, bVal);

Warning: 警告:

warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)

Can someone suggest on how can the template be re written to get value the right way ? 有人可以建议如何重写模板以正确的方式获得价值吗?

In your template for GetValue for ValType === bool , val is of type bool. ValType === bool GetValue模板中, val的类型为bool。 Thus the line val = v.val.nVal; 因此,行val = v.val.nVal; results in the warning. 导致警告。

In order to provide special code for special types, there is template specialization. 为了为特殊类型提供特殊代码,有模板特殊化。

You can specialize the function template like 您可以像这样专门化功能模板

template<class T>
void GetValue(Variant v, T & val);

template<>
void GetValue<int>(Variant v, int & val)
{
  if (v.type == Variant::_int)
    val = v.val.nVal;
}
template <>
void GetValue<bool>(Variant v, bool & val)
{
  if (v.type == Variant::_bool)
    val = v.val.bVal;
}

Note: v.type does not determine which one will be called, the argument does. 注意: v.type不能确定将调用哪个,而参数则可以。

First, as dyp already suggested in the comments, I would recommend looking at Boost.Variant . 首先,正如dyp在评论中已经建议的那样,我建议您看一下Boost.Variant

That said, the issue you're running into is that regardless of what type you're storing internally, every branch always has to be compiled the way you wrote it - and some of those branches might not make any sense (what if you added an array or some other POD type?) The way Boost solves this issue is by requiring the user to pass in a functor, and you call that functor with the right type: 就是说,您遇到的问题是,无论内部存储什么类型,每个分支总是必须以您编写它的方式进行编译-而且其中一些分支可能没有任何意义(如果您添加了数组还是其他POD类型?)Boost解决此问题的方法是要求用户传入函子,然后使用正确的类型调用该函子:

template <typename F>
void visit(Variant v, F visitor)
{
    if(v.type == Variant::_bool) {
        visitor(v.val.bVal);
    }
    else if(v.type == Variant::_int) {
        visitor(v.val.nVal);
    }
    // etc.
}

So then, you just write a visitor: 因此,您只需编写一个访客:

struct get_bool {
    void operator()(bool b) {
        bVal = b;
    }

    template <typename OTHER>
    void operator()(OTHER ) { }

    bool& bVal;
};

And use it: 并使用它:

bool bVal(false);
visit(v, get_bool{bVal});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM