【发布时间】:2020-04-05 15:34:04
【问题描述】:
我有一个persistence_manager_t 类,它向用户隐藏了可用的实现。
一种实现是使用SQLite,其返回码是 C 预处理定义为
#define SQLITE_OK 0 /* Successful result */
现在我正在尝试创建一个枚举类,而无需手动编写返回代码,即
// persistence_manager_t.cpp
#include <sqlite3.h>
enum class persistence_manager_status {
STATUS_OK = SQLITE_OK, STATUS_ROW = SQLITE_ROW, STATUS_DONE = SQLITE_DONE
};
但作为类用户尝试
auto rc = context->persistence->open(db_name);
if(rc != persistence_manager_status::STATUS_OK) {
// TODO: gestione errori
}
事实证明,枚举类应该在标题中定义,所以我要么必须在公共标题 persistence_manager.h 中包含 sqlite3.h,要么类用户应该在他们的实现中自己包含 sqlite3.h(很奇怪,因为他们需要安装 sqlite-dev)。
根据 C++17,枚举类实现是否也有前向声明或类似的东西?我们如何使用它?
【问题讨论】:
-
sqlite3.h中的状态值是否经常变化?如果没有,您可以使用枚举类中的值,并添加注释说明这些值是从 sqlite3.h 中逐字复制的,而不是更改它们。在 persistence_manager_t.cpp 中,您可以添加一些 static_assert 以确保枚举值与 sqlite3.h 值匹配,以捕捉是否有人弄乱了这些值。
-
这正是我所做的。但是,此解决方案也需要映射到实现中的 SQLITE_KEY。所以这里的脱钩似乎是乌托邦。
-
值得确保您的persistence_manager 没有“泄漏抽象”,其中persistence_manager 的客户端代码必须了解SQLite-isms。这样,当你用 DB2 或 Oracle 或 Azure 或 AWS 或 GCP 或 MySQL 或 PostgreSQL 或 MongoDB 或 LiteDB 或 Firebase 或 JSON 或 YAML 或 BSON 或 XML 替换 SQLite 时......你的客户端代码也不必是重构。不幸的是,这往往很困难,直到您不得不多次修改代码以找出适当的抽象障碍。
-
persistence_manager目前有泄漏的抽象,因为类的用户必须在他们的开发机器上安装 sqlite-dev。如果映射函数成功了,那么一切都会无缝地工作并且抽象完成。
标签: c++ sqlite class enums forward-declaration