不带类型参数的返回std :: make_unique

时间:2019-04-15 10:43:01

标签: c++

例如,我得到了以下代码:

#include <memory>

class A {
 public:
  A(int i, float f){};
  A(std::string){};
  ...
};

class B {
 public:
  B(int i){};
  B(float f){};
  ...
};

std::unique_ptr<A> getA() {
  if (some condition) {
    return std::make_unique<A>(1,1.0);
  } else if (some condition) {
    return std::make_unique<A>("test");
  }
}

std::unique_ptr<B> getB() {
        if (some condition) {
    return std::make_unique<B>(1);
  } else if (some condition) {
    return std::make_unique<B>(1.0);
  }
}

我可以只写这样的代码return std::make_unique(1,1.0);(否<A>)吗?我认为编译器知道返回类型,只有A类的构造函数参数在这一行中很重要。那有什么办法可以省略类型参数?

我想要这个,因为在实际问题中,有很多类类型(带有长名称),并且每个类都有很多构造函数,每次返回时都写return make::unique<*type*>(*parameters*)很烦人。

1 个答案:

答案 0 :(得分:3)

您可以使用具有正确的unique_ptr转换程序的帮助程序类来获取它:

#include <tuple>
#include <memory>
#include <utility>
template <class ...Ts>
class unique_ptr_maker : private std::tuple<Ts...>
{
  public:
    using std::tuple<Ts...>::tuple;
    template <class T>
    operator std::unique_ptr<T>() &&
    {
        return move_it<T>(std::make_index_sequence<sizeof...(Ts)>());
    } 
  private:
    template <class T, std::size_t... Is>
    std::unique_ptr<T> move_it(std::index_sequence<Is...>)
    {
        using parent = std::tuple<Ts...>;
        return std::make_unique<T>(
            std::forward<std::tuple_element_t<Is, parent>>( 
                std::get<Is>(*this))...);
    }
};

template <class ...Ts>
unique_ptr_maker<Ts...> get_unique_maker(Ts &&...ts)
{
    return unique_ptr_maker<Ts...>(std::forward<Ts>(ts)...);
}

那么用法是:

std::unique_ptr<B> getB() {
        if (some condition) {
    return get_unique_maker(1);
  } else if (some condition) {
    return get_unique_maker(1.0);
  }
}

说明

此解决方案分为两个阶段:

  1. 它将所有构造函数参数打包到一个元组中,该元组是unique_ptr_maker的父级。
  2. 元组的子元素unique_ptr_maker具有自动转换为unique_ptr的运算符。每当unique_ptr_maker恰好位于unique_ptr<T>的位置时,就会调用此运算符。

不幸的是,T(来自unique_ptr<T>)的构造函数的参数类型检查发生得很晚。结果,这些错误可能令人困惑。我看不到如何改善这种情况,因为无论如何在转换操作员之前都无法发现潜在的问题。

编辑

使它与仅移动参数一起使用。