我继承了Table Data Gateway实现,我正在尝试将一些运行时错误转换为编译时错误。表和类之间存在简单的一对一映射,但并非所有CRUD操作都适用于所有类型。有一个“经理”类模板(以简化形式)看起来像
template <typename T>
class object_manager
{
public:
void create(const T&){ /* SQL CREATE */ }
void update(const T&){ /* SQL UPDATE */ }
void del(const T&){ /* SQL DELETE */ }
template <OutIt> OutIt read(OutIt) const {/* SQL SELECT */}
private:
some_db_connection& m_db;
};
我想切换到mixin类型的实现,这样每个持久化类型都有一个关联的object_manager,它只从对该类型对象有效的操作构建。我发现如果我将CRUD函数分解为他们自己的类,那么
template <typename T>
class object_manager
{
public:
typedef T object_type;
protected:
some_db_connection& m_db;
};
template <typename Base>
class create_mixin : public Base
{
public:
typedef Base::object_type object_type;
void create(const object_type&) { /* sql INSERT */ }
};
template <typename Base>
class read_mixin : public Base
{
public:
typedef Base::object_type object_type;
template <OutIt> OutIt read(OutIt) const {/* SQL SELECT */}
};
template <typename Base>
class update_mixin : public Base
{
public:
typedef Base::object_type object_type;
void update(const object_type&) {/* SQL UPDATE*/}
};
template <typename Base>
class delete_mixin : public Base
{
public:
typedef Base::object_type object_type;
void del(const object_type&) {/* SQL DELETE*/}
};
然后我能够生成一个只有有效操作的类型,从而在编译类型中找到不正确的函数调用(例如尝试更新不可变类型)
//read-only
read_mixin<object_manager<some_persistent_type>> read_only_mgr;
//un-deletable
create_mixin<read_mixin<update_mixin<object_manager<some_persistent_type>>>> undeletable_mgr;
我希望能够在编译时从boost :: mpl :: vector生成这些object_manager类型,这样我就可以为列出的持久化类型创建一个traits类。有效的操作。
struct op_create;
struct op_read;
struct op_update;
struct op_delete;
template <typename T>
struct my_traits
{
typedef boost::mpl::vector<op_create, op_read, op_delete> valid_operations;
};
将某些符号名称(例如op_read,op_create等)映射到实际的mixin类是微不足道的,但我正在努力的是如何重新创建第三个代码块中显示的类型。我有一个模糊的概念,即boost :: mpl :: inherit_linearly会起作用,但我还不清楚所有部分是如何组合在一起的。
我应该提到我可以访问一个相对现代的Boost而不是c ++ 11。