Skip to content

Built-in Data Types Basic Data Types

This article introduces the basic data types.

IException

ICore supports the C++ exception mechanism. The IException class declaration is as follows:

class IException
{
public:
    IException(QString cause);
    virtual ~IException() = default;

public:
    const QString& getCause() const;

private:
    QString m_cause;
};

Notes

Please use exceptions cautiously during usage. Except in the following two scenarios, it is not recommended to use the exception mechanism.

  • When the call chain is deep with potential cyclic calls, but the call entry point is clear, it is recommended to use the exception mechanism. This allows capturing exceptions at the call entry point and throwing exceptions at any node in the call chain. For example, during HTML template parsing.
  • When external environments change, such as during database query operations. Under normal circumstances, this is not an issue. However, if problems arise, exceptions are more effective in addressing them.

Other scenarios do not recommend using exceptions. For more details on safety, please refer to the Security Policy documentation.

IRdbException

If users need to use IException, they should not use it directly. Instead, they should create subclasses and use the more semantically clear subclass type. Currently, the project supports the IRdbException subclass because database operations are unreliable and indeterminate.

Its usage is as follows:

template<typename T, bool enabled>
QSqlDatabase IRdbSqliteDatabaseInterface<T, enabled>::openDatabase()
{
    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());  // Throw an exception when creating the connection
    }

    return database;
}

ISqlQuery IRdbDatabaseWare::createQuery()
{
    if(auto db = lockConnection()){
        return ISqlQuery(db, m_dialect);
    }
    throw IRdbException("fail to create query");    // Throw an exception when the database connection is invalid.
}

In C++, thrown exceptions must be caught; otherwise, the entire program will crash. As shown above, IRdbException exceptions are caught during the HTTP request processing. If an exception is caught, a 500 status is returned to the user.

IJson

In ICore, we use nlohmann/json as our JSON tool. This is due to its advantages of high performance, ease of use, and comprehensive functionality. In ICore, we rename nlohmann/json to IJson. The code for IJson.h is as follows:

using IJson = nlohmann::json;
Q_DECLARE_METATYPE(IJson)

In the first line of code, we rename nlohmann/json to IJson. In the second line of code, we register IJson as a Qt meta-object type, enabling reflection usage of IJson.

Secondly, the naming convention of IJson aligns better with the naming conventions of ICore, making the code more natural and fluent.

In ICore programs, it is no longer recommended for users to use the nlohmann/json type to operate JSON data. Instead, they should use the shorter IJson type.

IJsonUtil

In ICore, to address the need for conversion between IJson and other data types, the IJsonUtil utility set is defined. It primarily includes two types of functions: fromJson and toJson.

fromJson

The declaration of IJsonUtil::fromJson is as follows:

// 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);

// Numeric types
template <typename T>
std::enable_if_t<std::is_arithmetic_v<T>, bool>
fromJson(T& data, const IJson& json);

// Bean types
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);

// Sequence containers
#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

From the above code, it can be seen that the basic signature of fromJson is:

1
2
3
4
5
namespace IJsonUtil
{
    template<typename T>
    bool fromJson(T&, const IJson&);
}

The type T can be:

  • Basic types: bool, QString, std::string, IString, IJson, QDate, QTime, QDateTime, QStringList.
  • Numeric types, including integer and floating-point types.
  • Bean types. For details on this type, refer to the Bean documentation.
  • Sequence containers: std::list, std::vector, QList, QVector.
  • Associative containers: std::map, QMap.

When the IJson conversion is successful, the return value is true. When it fails, the return value is false.

toJson

The basic signature of toJson is:

1
2
3
4
5
namespace IJsonUtil
{
    template<typename T>
    IJson toJson(T value);
}

The type T can be:

  • Basic types: bool, QString, std::string, IString, IJson, QDate, QTime, QDateTime, QStringList.
  • Numeric types, including integer and floating-point types.
  • Bean types. For details on this type, refer to the Bean documentation.
  • Sequence containers: std::list, std::vector, QList, QVector.
  • Associative containers: std::map, QMap.

toJson does not have scenarios where conversion fails.

IResult

IResult is a concise wrapper around std::optional.

template<typename T>
using IResult = std::optional<T>;

The purpose is to standardize the writing style.

IString

IStringView

IStringViewStash