首页 > 解决方案 > 通用对象实例化

问题描述

我有一堂课:

    class User {
    public:
        int id = 0;
        std::string email = "";

        User(int id_, std::string email_) :
        id(id_), email(email_) {}

    };

我可以像这样构造一个实例:

    auto x=Model::User({3,"m"});

但是我需要使用来自向量的数据来构造实例。我从数据库中获取这些数据,并希望使对象的构造具有通用性:

    auto v=std::vector<std::any>({3,"m"}); // from the db
    auto x=Model::User(v); // instanciate the object with a vector, does not work without special constructor.

无需修改类构造函数。是否可以使用参数包或 initializer_list 来做到这一点?

就像是

template<typename T>
T makeobject(vector<any> args) {
    // instanciate new object of type T, initialised with data from args
    // and return it
}

auto u=makeobject<User>(v);

标签: c++

解决方案


你可能会这样做:

User makeUser(const std::vector<std::any>& args) {
    return User(std::any_cast<int>(args[0]), std::any_cast<const char*>(args[1]));
}

由于 C++ 没有反射,要使其通用,您必须为要支持的每个类提供特征(或与magic_get兼容)

template <typename T, typename Tuple, std::size_t...Is>
T makeObject(std::index_sequence<Is...>, const std::vector<std::any>& args) {
    return T(std::any_cast<std::tuple_element_t<Is, Tuple>>(args[Is])...);
}

template <typename T>
T makeObject(const std::vector<std::any>& args) {
    using Tuple = typename T::TupleConstructor;
    return makeObject<T, Tuple>(std::make_index_sequence<std::tuple_size_v<Tuple>>(), args);
}

class User {
public:
    using TupleConstructor = std::tuple<int, const char*>;

    int id = 0;
    std::string email = "";

    User(int id_, std::string email_) :
    id(id_), email(email_) {}
};

可以使用外部 type_traits 代替直接添加别名类型 in User


推荐阅读