概述
- 在整理项目代码时,发现一个项目的封装挺有意思,摘取部分实现来说明。
- 背景:项目中不同类型的结构体数据,分别有增、删、改、查的需求,而数据是存在std::vector中的,因此考虑使用C++的模板和std::any实现相关业务逻辑,以复用增删改查业务逻辑代码。
- 这里涉及到一次数据格式转换,即auto&& vec = std::any_cast<std::vector&>(anyVec);
实现方法
class CIdGenerator
{
CIdGenerator(){
boost::uuids::uuid uuid = boost::uuids::random_generator()();
m_id = boost::lexical_cast<string>(uuid);
}
const std::string& to_str() {
return m_id; }
private:
std::string m_id;
};
class CBaseObjectManager
{
public:
CBaseObjectManager() = default;
~CBaseObjectManager()= default;
template<typename T>
int16_t GetObject(T& dst, const CIdGenerator& id, std::any anyVec)
{
int16_t ret = 0;
auto&& vec = std::any_cast<std::vector<T>&>(anyVec);
auto it = std::find_if(vec.begin(), vec.end(), [id](const T& t)
{
return t.GetId() == id;
});
if (it != vec.end())
{
dst = *it;
}
else
ret = -1;
return ret;
}
template<typename T>
int16_t AddObject(const T& src, std::any&& anyVec)
{
int16_t ret = 0;
ret = src.check();
if (SuccessStatus != ret)
return ret;
auto&& vec = *(std::any_cast<std::vector<T>*>(anyVec));
T t;
auto find = GetObject(t, src.GetId(), vec);
if (find == 0)
return -1;
t = src;
t.SetId(CIdGenerator());
vec.push_back(t);
return ret;
}
template<typename T>
int16_t UpdateObject(const T& src, const CIdGenerator& id, std::any&& anyVec)
{
int16_t ret = 0;
ret = src.check();
if (SuccessStatus != ret)
return ret;
auto&& vec = *(std::any_cast<std::vector<T>*>(anyVec));
auto it = std::find_if(vec.begin(), vec.end(), [id](const T& t)
{
return t.GetId() == id;
});
if (it != vec.end())
{
T src2 = src;
auto& tmp = *it;
std::swap(tmp, src2);
tmp.SetId(id);
}
else
ret = -1;
return ret;
}
template<typename T>
int16_t DeleteObject(const CIdGenerator& id, std::any&& anyVec)
{
int16_t ret = 0;
auto&& vec = *(std::any_cast<std::vector<T>*>(anyVec));
auto it = std::find_if(vec.begin(), vec.end(), [id](T& t)
{
return t.GetId() == id;
});
if (it != vec.end())
vec.erase(it);
else
return -1;
return ret;
}
};