1

我继承了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;
};

我想切换到混合类型的实现,这样每个持久类型都有一个关联的 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 类型,这样我就可以有一个用于列出有效操作的持久类型的特征类。

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。

4

0 回答 0