静态工厂方法的C ++类型推导

时间:2018-11-24 20:05:03

标签: c++ c++17 type-deduction

自C ++ 17起,现在实例化具有很多模板参数的类变得容易得多,这些模板参数可以从构造函数调用中自动推导。

在我的项目中,我有一个模板类的层次结构,可以将它们嵌套在一起,这会导致大量的类型名称,这就是为什么类模板参数推导如此出色的原因。

但是,我也使用静态工厂方法来简化类的动态构造(基本上,我只是返回包含新创建对象的shared_ptrs)。就像下面的示例一样

#include <iostream>
#include <memory>

template <typename T>
struct S {
    const std::shared_ptr<T> m_t;
    S(std::shared_ptr<T> t):
        m_t {std::move(t)} {}

    template<typename ...Args>
    static S create(Args&&... args);
};

template <typename T>
template <typename ...Args>
std::shared_ptr<S<T>> S<T>::create(Args&&... args) {
    return std::make_shared<S<T>>(std::forward<Args>(args)...);
}




int main() {
    auto s1 = S{std::make_shared<int>(6)};
    // auto s2 = S::create(std::make_shared<int>(5));   // DOESN'T work
}

我需要使用指针来启用多态性(除非有另一种不需要指针的方式-可能是CRTP),但是我看不到任何方法可以简化实例化过程,而无需指定返回的完整类型在某处物体。

1 个答案:

答案 0 :(得分:2)

template <typename ...Args>
auto createS(Args&&... args) {
    return std::make_shared<decltype(S{std::forward<Args>(args)...})>(std::forward<Args>(args)...);
}

int main() {
    auto s1 = S{std::make_shared<int>(6)};
    auto s2 = createS(std::make_shared<int>(5));
}

这应该确保推导类型与s1完全相同。

实际上,您可以将其概括为任何类模板参数推导:

template <template<typename...> class Tmpl, typename ...Args>
auto make_shared_deduced(Args&&... args) {
    return std::make_shared<decltype(Tmpl{std::forward<Args>(args)...})>(std::forward<Args>(args)...);
}

int main() {
    auto s1 = S{std::make_shared<int>(6)};
    auto s2 = make_shared_deduced<S>(std::make_shared<int>(5));
}

另请参阅standard proposal P1069R0

您是否真的想要所有这些shared_ptr我都不知道。可能只应在非常特殊的情况下使用它们,而不是一般那样。