是吗?我不知道如何给C++添加反射。因此,在开发自己的解决方案之前,我需要先熟悉Boost概念。不管怎样,只要用宏标记成员,自动为其分配数据库列,那就太酷了。尽管在我的案例中,这显然是不必要的,但出于学习的目的,我可以尝试一下。自从我开始实施以来,我最初的

是吗?我不知道如何给C++添加反射。因此,在开发自己的解决方案之前,我需要先熟悉Boost概念。不管怎样,只要用宏标记成员,自动为其分配数据库列,那就太酷了。尽管在我的案例中,这显然是不必要的,但出于学习的目的,我可以尝试一下。自从我开始实施以来,我最初的,c++,sql,templates,types,struct,C++,Sql,Templates,Types,Struct,是吗?我不知道如何给C++添加反射。因此,在开发自己的解决方案之前,我需要先熟悉Boost概念。不管怎样,只要用宏标记成员,自动为其分配数据库列,那就太酷了。尽管在我的案例中,这显然是不必要的,但出于学习的目的,我可以尝试一下。自从我开始实施以来,我最初的问题,即需要一个数据结构来容纳一行,又出现了。我更新了问题,尽可能简明扼要地解释了这个问题。你能分享一下你的想法吗?@danijar:你现在所做的看起来很像性格特征。例如,在标准库中,std::basic_string的第二个模板参数默认为st


是吗?我不知道如何给C++添加反射。因此,在开发自己的解决方案之前,我需要先熟悉Boost概念。不管怎样,只要用宏标记成员,自动为其分配数据库列,那就太酷了。尽管在我的案例中,这显然是不必要的,但出于学习的目的,我可以尝试一下。自从我开始实施以来,我最初的问题,即需要一个数据结构来容纳一行,又出现了。我更新了问题,尽可能简明扼要地解释了这个问题。你能分享一下你的想法吗?@danijar:你现在所做的看起来很像性格特征。例如,在标准库中,
std::basic_string
的第二个模板参数默认为
std::char_traits
。通过创建一个“基本”trait并为您需要存储的每个结构专门化它,trait可以提供(反)序列化方法,您可以通过模板代码访问它们(即,无需注册)。当然,它的美妙之处在于,您不需要实际修改
Person
本身。感谢您指出这一点。我会查一查。这种特质起着注册的作用,所以我不知道什么更好。但traits似乎比我的转换函数方法更受欢迎,因此对其他人来说更具可读性。您还会将我的代码示例中的特征存储在
列表中吗?列表的类型可以是
std::unordered_map
。@danijar:不,一点也不。这就是这种特质的优点。编写
DbTrait::Serialize
时,编译器知道在没有额外注册表的情况下使用
DbTrait
的哪个专门化。因为没有额外的注册表,所以不需要基类和统一的函数签名。
struct Person
{
    std::string Name;
    int Age;

    // more members that shouldn't be stored or loaded
    // ...
};
// example for storing
unsigned int id = 42;          // not hardcoded of course
Person paul = { "Paul", 8 };   // instantiate the struct
Data->Save<Person>(id, *paul); // table name is derived from template argument

// example for fetching
unsigned int id = 42;
Person paul;
Data->Load<Person>(id, *paul);
class Data
{
    typedef std::function<row(T*) Serialization;
    typedef std::function<void(row, T*) Deserialization;
    typedef std::pair<Serialization, Deserialization> Registereds;
    std::unordered_map<std::type_index, Registered> List;
public:
    template <typename T>
    Register<T>(std::function<row(T*) Serialize,
                std::function<void(row, T*) Deserialize)
    {
        // create a table based on the template argument
        std::string name = typeid(T).name();
        // ...

        // add conversion functions to the list
        auto index = std::type_index(typeid(T));
        List.insert(index, std::make_pair(Serialize, Deserialize));
    }

    // load and save functions shown above go here
    // ...
};
Data->Register<Person, std::string, int>(
    [](Person *Instance) -> std::tuple<std::string, int>{ /* ... */ }, 
    [](std::tuple<std::string, int> Row, Person *Instance) -> void{ /* ... */ }
);
template <class T>
struct data_traits{ };

struct data_traits<Person>
{
    struct row{ int Age; std::string Name; }; // right to do here?
    row serialize(Person *Instance)
    {
        // ...
    }
    void deserialize(row Data, Person *Instance)
    {
        // ...
    }
};
class Data
{
    template <typename T>
    void Load(uint64_t Id, T *Instance)
    {
        auto traits = data_traits<T>;

        std::string query = "SELECT * FROM "
                          + typeid(T).name()
                          + " WHERE id = "
                          + std::to_string(Id);
        // fetch result from database
        // ...

        traits::row result;
        // convert SQL result into type dependent row type
        // but how to do that?
        // ...

        traits.deserialize(result, Instance);
    }
};
struct Person {
    struct Name: Field<std::string> { static char const* N() { return "name"; } }
    struct Age: Field<int> { static char const* N() { return "age"; } }

    Name name;
    Age age;
}; // struct Person

BOOST_FUSION_ADAPT_STRUCT(
    Person,
    (Name, name)
    (Age, age))