内置数据类型 基础数据类型
本文介绍基础的数据类型
IException
ICore中支持c++ exception 的机制。exception 的类声明如下:
| class IException
{
public:
IException(QString cause);
virtual ~IException() = default;
public:
const QString& getCause() const;
private:
QString m_cause;
};
|
注意事项
exception 在使用过程中请谨慎使用,除了在以下的两种情形之外,不建议使用异常机制。
- 在函数调用链过深,有循环调用等, 但是调用入口是明确的情况下,建议使用异常机制。这样可以在调用的入口处捕获异常,在调用中的节点随时抛出异常。比如做 html 模板解析的时候。
- 在网络连接等外部环境变化的情况下,比如数据库查询操作。这个在正常情况下是没有问题的,如果出现问题,则通过异常更能解决问题。
其他的情况不建议使用 exception。更多关于安全的内容,请查看安全策略 的文档。
IRdbException
如果用户需要使用 IException,请不要直接使用,需要生成子类之后,使用子类这种具有更明确语义的类型。在目前的项目进展中,目前支持 IRdbException子类。这个是由于数据库操作是一个不可靠,不确定的操作。
他的使用方式如下:
| template<typename T, bool enabled>
QSqlDatabase IRdbSqliteDatabaseInterface<T, enabled>::openDatatbase()
{
QSqlDatabase database;
database = QSqlDatabase::addDatabase(this->m_dataSource.driverName, IMetaUtil::getTypeName<T>() + "_0");
database.setDatabaseName(this->m_dataSource.databaseName);
if(!database.open()){
throw IRdbException(database.lastError()); // 在创建连接的时候抛出异常
}
return database;
}
ISqlQuery IRdbDatabaseWare::createQuery()
{
if(auto db = lockConnection()){
return ISqlQuery(db, m_dialect);
}
throw IRdbException("fail to create query"); // 在数据库connection invalid 的时候 抛出异常。
}
|
在 c++ 中,抛出的异常一定要被拦截掉,不然整个程序就会崩溃掉。如上,IRdbException 抛出的异常在 Http 请求处理的过程中被拦截。如果拦截到异常,则会返回用户 500 状态。
IJson
在我们ICore中,使用nlohmann/json作为我们的 json 工具。这是由于 nlohmann/json 高性能,易用性和功能全面的优点。在ICore中,我们使用 IJson 来重命名 nlohmann/json。如下是 IJson.h 的代码
| using IJson = nlohmann::json;
Q_DECLARE_METATYPE(IJson)
|
在第一行代码中,我们重命名了 nlohmann/json 为 IJson, 第二行代码我们将 IJson 注册为 Qt的元对象类型,使IJson 可以被反射使用。
其次 IJson 的命名习惯更符合 ICore 的命名习惯,使代码更加自然流畅。
在 ICore程序中,不再建议用户使用 nlohmann/json 类型去操作 json 数据,而是使用更加简短的 IJson 类型。
IJsonUtil
在ICore中,应对于IJson和其他数据类型相互转换的需求,定义了 IJsonUtil 的工具集,它主要包括 两类的函数 fromJson 和 toJson。
fromJson
IJsonUtil::fromJson 的声明如下:
| // basic types
inline bool fromJson(bool& data, const IJson& json);
inline bool fromJson(QString& data, const IJson& json);
inline bool fromJson(std::string& data, const IJson& json);
inline bool fromJson(IString& data, const IJson& json);
inline bool fromJson(IJson& value, const IJson& json);
inline bool fromJson(QDate& value, const IJson& json);
inline bool fromJson(QTime& value, const IJson& json);
inline bool fromJson(QDateTime& value, const IJson& json);
inline bool fromJson(QStringList& value, const IJson& json);
// numbers
template <typename T>
std::enable_if_t<std::is_arithmetic_v<T>, bool>
fromJson(T& data, const IJson& json);
// beans
template<typename T>
std::enable_if_t<ITraitUtil::has_class_member_loadJson_v<T>, bool>
fromJson(T& data, const IJson& json);
// std::map
template<typename T, typename U>
bool fromJson(std::map <T, U>& data, const IJson& json);
// qmap
template<typename T, typename U>
bool fromJson(QMap <T, U>& data, const IJson& json);
// list / vector
#define PP_FROM_JSON_SEQUENCE_CONTAINER(Type) \
template<typename T> \
bool fromJson( Type <T>& data, const IJson& json) \
{ \
if(!json.is_array()) return false; \
for(const IJson& val : json){ \
T bean; \
if(!(::IWebCore::IJsonUtil::fromJson(bean, val))) return false; \
data.push_back(std::move(bean)); \
} \
return true; \
}
PP_FROM_JSON_SEQUENCE_CONTAINER(QList)
PP_FROM_JSON_SEQUENCE_CONTAINER(QVector)
PP_FROM_JSON_SEQUENCE_CONTAINER(std::list)
PP_FROM_JSON_SEQUENCE_CONTAINER(std::vector)
#undef PP_FROM_JSON_SEQUENCE_CONTAINER
|
在上述的代码中,可以看见, fromJson 的基本签名是:
| namespace IJsonUtil
{
template<typename T>
bool from Json(T&, const IJson&);
}
|
其中T 的类型可以为:
- 基础类型:bool, QString, std::string, IString, IJson, QDate, QTime, QDateTime, QStringList,
- 数值类型, 包括整型和浮点类型。
- Bean 类型。关于该类型,请参考 Bean 相关的文档。
- std::list, std::vector, QList, QVector 序列容器。
- std::map, QMap, 关联容器类型。
当IJson 转换成功的时候,返回值为 true, 当不成功的时候,返回值是false。
toJson
toJson 的基本签名是:
| namespace IJsonUtil
{
template<typename T>
IJson toJson(T value);
}
|
其中 T 的类型可以是:
- 基础类型:bool, QString, std::string, IString, IJson, QDate, QTime, QDateTime, QStringList,
- 数值类型, 包括整型和浮点类型。
- Bean 类型。关于该类型,请参考 Bean 相关的文档。
- std::list, std::vector, QList, QVector 序列容器。
- std::map, QMap, 关联容器类型。
toJson 不会有转换不成功的情形.
IResult
IResult 是对 std::optional 的简短封装
| template<typename T>
using IResult = std::optional<T>;
|
就是这么简单.这么做的目的是统一书写方式.
IString
IStringView
IStringViewStash