背景:从csv读取数据,并赋值到对应结构体字段。
由于读取出来的数据为string,需要根据结构体字段类型逐一赋值;
/// 假定要赋值的结构体类型
struct stStudent
{
char name[64];
int age;
double score;
stStudent()
{
memset(this, 0x00, sizeof(*this));
}
};
/// 假设从csv读取内容放到vector
std::vector<std::vector<std::string>> csvConetnt = { {"Jack", "10","82."},{"Mick", "10","80.5"} };
一、 以下写法直接把string转为相应类型没有问题;
缺点:但是如果结构体的字段、或结构体过多的话,我们就要知道左值的类型,然后使用 stod、stoi、stoll等等做类型转换,无疑麻烦的要死,并且还极有可能转换出错。
void paraseVector()
{
stStudent student;
for (auto& item : csvConetnt)
{
strcpy(student.name,item[0].c_str());
student.age = stoi(item[1]);
student.score = stod(item[2]);
}
}
二、使用std::is_same_v、std::decay_t和if constexpr 一劳永逸的解决赋值问题;
以下就不需要我们根据左值类型使用相应的类型转化,还解决了赋值过程中可能出现的类型赋值错误问题;只需要在getValue添加自己的类型就行了。
/// 推导退化类型
#define Type(type) std::decay_t<decltype(type)>
/// getValue
template <typename T>
T getValue( const std::string& strElement )
{
if constexpr ( std::is_same_v<T, int> )
{
return std::stoi(strElement);
}
else if constexpr ( std::is_same_v<T, char*> )
{
return (char(*))strElement.c_str();
}
else if constexpr ( std::is_same_v<T, double> )
{
return std::stod(strElement);
}
return T();
}
/// ...
void paraseVector()
{
stStudent student;
for (auto& item : csvConetnt)
{
strcpy(student.name, getValue<Type(student.name)>(item[0]));
student.age = getValue<Type(student.age)>(item[1]);
student.score = getValue<Type(student.score)>(item[2]);
}
}