C++ return std::make_unique不带类型参数

C++ return std::make_unique不带类型参数,c++,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_un

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

#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);
  }
}
#包括
甲级{
公众:
A(int i,float f){};
(std::string){};
...
};
B类{
公众:
B(int i){};
B(浮点数f){};
...
};
std::unique_ptr getA(){
如果(某些条件){
返回标准::使_唯一(1,1.0);
}否则如果(某些条件){
返回标准::使_唯一(“测试”);
}
}
std::unique_ptr getB(){
如果(某些条件){
返回标准::使_唯一(1);
}否则如果(某些条件){
返回标准::使_唯一(1.0);
}
}
我可以这样写代码吗
return std::make_unique(1,1.0)(否
)?我认为编译器知道返回类型,在这一行中只有类A的构造函数参数起作用。那么有没有办法省略类型参数


我想这样做是因为在实际问题中,有很多类类型(名称很长),每个类都有很多构造函数,每次返回时编写
return make::unique(*parameters*)
都很烦人

您可以通过一个helper类获得它,该类具有到unique的正确转换器\u 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)...);
}
#包括
#包括
#包括
模板
类唯一\u ptr\u生成器:私有std::tuple
{
公众:
使用std::tuple::tuple;
模板
运算符std::unique_ptr()&&
{
返回move_it(std::make_index_sequence());
} 
私人:
模板
std::unique_ptr move_it(std::index_序列)
{
使用parent=std::tuple;
return std::make_unique(
标准::转发(
std::get(*this))…);
}
};
模板
唯一的制造商获取唯一的制造商(Ts&&…Ts)
{
返回唯一的\u ptr\u生成器(std::forward(ts)…);
}
那么用法是:

std::unique_ptr<B> getB() {
        if (some condition) {
    return get_unique_maker(1);
  } else if (some condition) {
    return get_unique_maker(1.0);
  }
}
std::unique_ptr getB(){
如果(某些条件){
返回获取唯一制造商(1);
}否则如果(某些条件){
返回get_unique_maker(1.0);
}
}
解释 此解决方案分两个阶段工作:

  • 它将所有构造函数参数打包在一个元组中,元组是unique_ptr_maker的父级
  • 元组的子元素unique_ptr_maker具有一个自动转换操作符,可以将其转换为
    unique_ptr
    。只要unique_ptr_生成器恰好位于预期的
    unique_ptr
    位置,就会调用此运算符
  • 不幸的是,
    T
    (来自
    unique\u ptr
    )的构造函数参数的类型检查发生得很晚。因此,这些错误可能会令人困惑。我看不出如何才能使情况变得更好,因为在转换操作符之前无法检测到潜在的问题

    编辑
    使其仅适用于移动参数。

    您可以使用具有正确的唯一转换器的帮助器类来获得它。\u 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)...);
    }
    
    #包括
    #包括
    #包括
    模板
    类唯一\u ptr\u生成器:私有std::tuple
    {
    公众:
    使用std::tuple::tuple;
    模板
    运算符std::unique_ptr()&&
    {
    返回move_it(std::make_index_sequence());
    } 
    私人:
    模板
    std::unique_ptr move_it(std::index_序列)
    {
    使用parent=std::tuple;
    return std::make_unique(
    标准::转发(
    std::get(*this))…);
    }
    };
    模板
    唯一的制造商获取唯一的制造商(Ts&&…Ts)
    {
    返回唯一的\u ptr\u生成器(std::forward(ts)…);
    }
    
    那么用法是:

    std::unique_ptr<B> getB() {
            if (some condition) {
        return get_unique_maker(1);
      } else if (some condition) {
        return get_unique_maker(1.0);
      }
    }
    
    std::unique_ptr getB(){
    如果(某些条件){
    返回获取唯一制造商(1);
    }否则如果(某些条件){
    返回get_unique_maker(1.0);
    }
    }
    
    解释 此解决方案分两个阶段工作:

  • 它将所有构造函数参数打包在一个元组中,元组是unique_ptr_maker的父级
  • 元组的子元素unique_ptr_maker具有一个自动转换操作符,可以将其转换为
    unique_ptr
    。只要unique_ptr_生成器恰好位于预期的
    unique_ptr
    位置,就会调用此运算符
  • 不幸的是,
    T
    (来自
    unique\u ptr
    )的构造函数参数的类型检查发生得很晚。因此,这些错误可能会令人困惑。我看不出如何才能使情况变得更好,因为在转换操作符之前无法检测到潜在的问题

    编辑
    使其仅适用于移动参数。

    每当您看到类似的内容时,它都会告诉您有更好的方法来构造代码。@斯塔克:有什么建议吗?当然,为什么是模板。这就是模板的用途。我不认为幻想这是可能的有什么错。类似于
    std::make_unique
    ?这就是为什么我对这个问题投了赞成票。如果我知道的话,你为什么要这样做?每当你看到这样的事情,它就会告诉你有更好的方法来构造你的代码。@斯塔克:有什么建议吗?当然,为什么是模板。这就是模板的用途。我不认为幻想这是可能的有什么错。类似于
    std::make_unique
    ?这就是为什么我对这个问题投了更高的票。如果我知道的话,你为什么要这么做?这很有效。真遗憾,我连这个代码都不懂。您是否使用SFINE来确定哪个构造函数适合get_unique_maker()的参数?@reavenisadesk No SFINAE。我在答案中添加了一些解释,希望能澄清谜团。谢谢,我很少使用转换运算符,现在我完全理解了你的代码。它很有效。真遗憾,我连这个代码都不懂。您是否使用SFINE来确定哪个构造函数适合get_unique_maker()的参数?@reavenisadesk No SFINAE。我在答案中添加了一些解释,希望能澄清谜团。谢谢,我很少使用转换运算符,现在我完全理解了你的代码。