C++ 使用联合数组中的数据初始化std::vector

C++ 使用联合数组中的数据初始化std::vector,c++,C++,如何从结构数组初始化std::vector,其中结构包含不同类型的并集。换句话说,数组用于存储一系列特定类型的值,可以是int、char*等 到目前为止,这是我的解决方案,但我正在寻找更好的方法: 如果convert函数存储ints,则返回vector;如果convert函数存储char*,则返回vector 下面的值类型是包含名为Value的联合的结构。下面的容器类指向此类值的缓冲区 // union member getter class Getter { public: void

如何从结构数组初始化std::vector,其中结构包含不同类型的并集。换句话说,数组用于存储一系列特定类型的值,可以是int、char*等

到目前为止,这是我的解决方案,但我正在寻找更好的方法:

如果convert函数存储
int
s,则返回
vector
;如果convert函数存储
char*
,则返回
vector

下面的值类型是包含名为Value的联合的结构。下面的容器类指向此类值的缓冲区

// union member getter
class Getter
{
public:

    void operator()(int8_t& i, const Value& value)
    {
        i = value.value.i;
    }

    void operator()(std::string& s, const Value& value)
    {
       s = std::string(value.value.s);
    }

    ...
};

template<class T>
std::vector<T> convert(Container* container)
{
    std::vector<T> c;
    c.reserve(container->nrOfValues);
    Getter g;
    for(int i=0;i<container->nrOfValues;i++)
    {
        T value;
        g(value, container->values[i]);
        c.push_back(value);
    }
    return c;
}
//联合成员getter
类吸气剂
{
公众:
void运算符()
{
i=值。值。i;
}
void运算符()
{
s=std::string(value.value.s);
}
...
};
模板
标准::向量转换(容器*容器)
{
std::向量c;
c、 保留(容器->nrOfValues);
吸气剂g;
for(int i=0;inrof值;i++)
{
T值;
g(值,容器->值[i]);
c、 推回(值);
}
返回c;
}

您的问题是,union为每个值指定了不同的名称,这导致需要一个将名称转换为类型的函数,例如Getter::operator()返回类型并获取union的命名成员

你对此无能为力。您可以在每个项上保存变量声明和副本/字符串构造函数,但仅此而已

如果无法修改原始结构,则可以使用默认值的长度集(必须传入)初始化向量,然后使用getter进行迭代,如下所示:

vector<T> v(length, defaultValue);
typename vector<T>::iterator iter = vec.begin();
for(int index = 0; *iter != vec.end() && index < length; ++iter, ++index) {
  converter(*iter, array[index]);
}
然后,for循环变为:

for(int i=0;i<container->nrOfValues;i++)
{
    c.push_back(container->values[i]);
}
for(int i=0;inrof值;i++)
{
c、 向后推(容器->值[i]);
}

注意:您可以创建向量并将其作为参数传递给copy函数,因为它涉及在返回过程中复制数据。

如果您喜欢一些模板魔术,您可以使用稍微不同的方法:

// Source union to get data from
union U
{
  int i;
  char* s;
  double d;
};

// Conversion type template function (declared only)
template <class T> T convert(const U& i_u);

// Macro for template specializations definition
#define FIELD_CONV(SrcType, DestField)\
template <> SrcType convert(const U& i_u)\
{ auto p = &DestField; return i_u.*p; }

// Defining conversions: source type -> union field to get data from
FIELD_CONV(int, U::i)
FIELD_CONV(std::string, U::s)
FIELD_CONV(double, U::d)

// Get rid of macro that not needed any more - just for macro haters ;-)
#undef FIELD_CONV

// Usage
template<class T> std::vector<T> convert(Container* container)
{
   std::vector<T> c;
   c.reserve(container->nrOfValues);
   for(int i = 0; i < container->nrOfValues; ++i)
     c.push_back(convert<T>(container->values[i])); 
   return c;
} 
//要从中获取数据的源联合
联合大学
{
int i;
char*s;
双d;
};
//转换类型模板函数(仅声明)
模板T转换(常量U和i_);
//模板专门化定义的宏
#定义字段\u CONV(SrcType,DestField)\
模板SrcType转换(常量U和i_)\
{auto p=&DestField;return i_.*p;}
//定义转换:源类型->从中获取数据的联合字段
字段_CONV(int,U::i)
字段_CONV(标准::字符串,U::s)
字段_CONV(双精度,U::d)
//摆脱不再需要的宏-只针对讨厌宏的人;-)
#未定义字段\u CONV
//用法
模板std::向量转换(容器*容器)
{
std::向量c;
c、 保留(容器->nrOfValues);
对于(inti=0;inrOfValues;++i)
c、 向后推(转换(容器->值[i]);
返回c;
} 
这种方法的优点是:它简短、简单且易于扩展。将新字段添加到union时,只需编写另一个
字段\u CONV()
定义


编译的示例是。

请澄清。1.保证只包含值为single type和2的联合的容器。检查哪些类型的容器值(以确定
T
的类型)不是
convert
责任,而是在其他地方完成的?@Rost容器保证只包含单一类型的值。容器包含的类型不是convert的责任。谢谢您的回复!为什么要包括*iter!=在for循环中,vec.end()&&index>有可能是有人搞砸了。但是如果有人在上面的例子中搞砸了,单元测试会不会被抓住?我真的不喜欢宏。。。当然,我可能只是在现实生活中这样做,但我真的,真的,真的不喜欢宏;-)在现实生活中,我们经常做我们不喜欢的事情…@乔纳森补充道:“这只是为了你:-)好吧,这让我感觉好多了。:-)但是,我还是讨厌他们;-)很抱歉有太多的错误和错误代码。。。正如我所说,我可能会在现实生活中这样做,但我不喜欢这样做。@JonathanSeng实际上对宏的邪恶估计过高了。如果使用得当和小心,它们是强大而有用的工具。
// Source union to get data from
union U
{
  int i;
  char* s;
  double d;
};

// Conversion type template function (declared only)
template <class T> T convert(const U& i_u);

// Macro for template specializations definition
#define FIELD_CONV(SrcType, DestField)\
template <> SrcType convert(const U& i_u)\
{ auto p = &DestField; return i_u.*p; }

// Defining conversions: source type -> union field to get data from
FIELD_CONV(int, U::i)
FIELD_CONV(std::string, U::s)
FIELD_CONV(double, U::d)

// Get rid of macro that not needed any more - just for macro haters ;-)
#undef FIELD_CONV

// Usage
template<class T> std::vector<T> convert(Container* container)
{
   std::vector<T> c;
   c.reserve(container->nrOfValues);
   for(int i = 0; i < container->nrOfValues; ++i)
     c.push_back(convert<T>(container->values[i])); 
   return c;
}