使用联合数组中的数据初始化std::向量
Initialise a std::vector with data from an array of unions
如何从结构数组初始化std::向量,其中结构包含不同类型的并集。换句话说,数组用于存储特定类型的多个值,这些值可以是int、char*等。
到目前为止,这是我的解决方案,但我正在寻找更好的方法:
如果convert函数存储int
s,则返回vector<int>
;如果它存储char*
,则返回vector<std::string>
。
下面的Value类型是一个包含名为Value的并集的结构。下面的Container类指向这样的值的缓冲区。
// 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::operator()返回类型并获取并集的命名成员。
你对此无能为力。您可以在每个项上保存一个变量声明和一个副本/字符串构造函数,但仅此而已
如果不能修改原始结构,可以使用默认值的长度集初始化向量(必须传入),然后使用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]);
}
请注意,在迭代索引和迭代器并验证两者在发生意外时仍然有效时,这开始变得很麻烦。。。
如果可以修改原始结构:
class Ugly { // or struct, it doesn't matter
public:
union {
char* s;
int i;
} value;
Ugly(char* s) {
value.s = s;
}
Ugly (const int& i) {
value.i = i;
}
operator std::string() const {
return std::string(value.s);
}
operator int() const {
return value.i;
}
};
然后你的for循环变成:
for(int i=0;i<container->nrOfValues;i++)
{
c.push_back(container->values[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;
}
这种方法的优点是短、简单且易于扩展。当您向并集添加新字段时,您只需编写另一个FIELD_CONV()
定义。
编译的示例在这里。
相关文章:
- 如何使用数据对象上的常量指针初始化类
- C++中数据初始化的不同方式
- 在没有默认构造函数时使用垃圾数据初始化对象
- 如何使用派生类类型数据初始化 std::shared_ptr?
- 委派复制构造函数和常量数据初始化
- 从其后声明的另一个成员数据初始化成员数据是否为未定义行为
- 使用类/对象实例数据初始化对话框
- 使用数据初始化 cv::Mat 不起作用
- 使用函数中的数据初始化C++ const 成员 (MPI_comm_size/rank)
- 如何故意用未初始化的数据初始化变量,以便valgrind将该变量视为未初始化
- 使用通用数据初始化多个C++数组
- 特征库 --> 使用文件或现有 std::vector<string> content (c++) 中的数据初始化矩阵
- 使用联合数组中的数据初始化std::向量
- 新操作员的内存分配和数据初始化
- 用动态分配的数据初始化cv::Mat
- 如何用预制数据初始化指针到指针
- 如何用该类的其他成员数据初始化类成员数据
- c++中静态数据初始化的时间和方式
- 将大量数据初始化到C++容器中的最佳方法
- 如何使用浮点数组中的数据初始化 cv::Mat