运行时在类之间进行选择以进行实例化

问题描述 投票:0回答:1

我想构造一个在运行时根据

enum class
值选择的类型的对象。类
A
B
有多个构造函数,这些构造函数具有不同数量的参数,可以在运行时使用。我尝试编写一个工厂方法,将
shared_ptr
返回到基类来尝试解决此问题。 这是我的错误尝试:

enum class Type
{
    A,
    B // C, etc
};

struct Base{};

struct A : public Base
{
    A(const int a) { std::cout << "A::A(int)"; }
    A(double d) { std::cout << "A::A(double)"; }
    A(int a, double d) { std::cout << "A::A(int,double)"; }
};

struct B : public Base
{
    B(int i, double d) { std::cout << "B::B(double)"; }
    B(int a, double d, double dd) { std::cout << "B::B(int,double, double)"; }
};

template <typename... Args>
std::shared_ptr<Base> make_Type(Type t, Args &&...args)
{
    if (t == Type::A)
        return std::make_shared<A>(std::forward<Args>(args)...);
    else if (t == Type::B)
        return std::make_shared<B>(std::forward<Args>(args)...);
    else
        assert(false);
}

毫无疑问,这是行不通的。我可以使用

if constexpr
创建静态版本。但如何尝试运行时版本呢? (可能不使用
typeinfo
)。 也欢迎任何替代方法。

c++ variadic-templates template-meta-programming
1个回答
0
投票

您可能正在寻找这样的东西:

template <typename T, typename... Args>
std::enable_if_t<std::is_constructible_v<T, Args&&...>, std::shared_ptr<T>>
safe_make_shared(Args&&... args) {
    return std::make_shared<T>(std::forward<Args>(args)...);
}

template <typename T>
std::shared_ptr<T> safe_make_shared(...) { return nullptr; }

template <typename... Args>
std::shared_ptr<Base> make_Type(Type t, Args &&...args)
{
    switch (t) {
        case Type::A : return safe_make_shared<A>(std::forward<Args>(args)...);
        case Type::B : return safe_make_shared<B>(std::forward<Args>(args)...);
        default: assert(false); return nullptr;
    }
}

演示

这个想法是有一个

safe_make_shared
函数,如果类型实际上可以使用给定的参数集构造,则创建对象,否则返回 null (或者它可以断言,或抛出异常作为后备)。重要的是
safe_make_shared
可以使用任何参数集进行实例化,但仅尝试将“正确”的参数集传递给对象的构造函数。

© www.soinside.com 2019 - 2024. All rights reserved.