std :: make_unique(以及emplace,emplace_back的)对initializer_list参数的尴尬推论

红宝石

说我有这个结构:

struct position
{
  int x, y;
};

和另一个将其作为构造函数参数的类:

class positioned
{
public:
  positioned(position p) : pos(p) {}
private:
  position pos;
};

我如何获得简单

auto bla = std::make_unique<positioned>({1,2});

上班?

目前,编译器尝试通过进行匹配,initializer_list<int>并调用的数组变量make_unique,这很愚蠢,因为positioned它只有一个构造函数。对于emplaceemplace_back功能也会出现相同的问题将其可变参数模板参数转发给类的构造函数的几乎任何函数似乎都表现出这种行为。

我知道我可以通过以下方式解决此问题

  1. 提供positioned两个int参数的构造函数,并将{}中的调用删除make_unique,或
  2. 将参数的类型明确指定为make_uniqueas position{1,2}

在我看来,这两者似乎都太冗长了(在make_unique实现中付出了一些努力),这可以解决而无需参数类型的这种过分规范。

这是实现中可解决的缺陷,make_unique还是一个没人要关心的无法解决,无趣的边缘情况?

尼科尔·波拉斯(Nicol Bolas)

当获得括号初始列表时,功能模板实参推导不起作用。它仅根据实际表达式起作用。

还应注意,无论如何positioned都不能对列表进行初始化{1, 2}这将尝试调用两个参数的构造函数,并且positioned没有此类构造函数。您将需要使用positioned({1, 2})positioned{{1, 2}}

这样,一般的解决方案是以make_unique某种方式神奇地为正在构造的类型重现每个可能的构造函数的签名。目前,这显然不是在C ++中要做的合理的事情。

一种替代方法是使用lambda创建对象,并make使用C ++ 17的保证省略规则编写替代函数,以将返回的prvalue应用于内部new表达式:

template<typename T, typename Func, typename ...Args>
std::unique_ptr<T> inject_unique(Func f, Args &&...args)
{
  return std::unique_ptr<T>(new auto(f(std::forward<Args>(args)...)));
}

auto ptr = inject_unique<positioned>([]() {return positioned({1, 2});});

您甚至可以抛弃typename T参数:

template<typename Func, typename ...Args>
auto inject_unique(Func f, Args &&...args)
{
  using out_type = decltype(f(std::forward<Args>(args)...));
  return std::unique_ptr<out_type>(new auto(f(std::forward<Args>(args)...)));
}

auto ptr = inject_unique([]() {return positioned({1, 2});});

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

带有std :: make_unique的push_back或emplace_back

Lambda作为std :: vector :: emplace_back的参数

使用std :: vector :: emplace_back

std :: vector上的emplace_back

c++ std::map`emplace`和`emplace_back`重载

为什么std :: string没有emplace或emplace_back?

std :: vector :: emplace_back和std :: move

为什么此std :: vector :: emplace_back失败?

std :: vector <> :: emplace_back()中的异常安全吗?

右值引用上的std :: vector <T> :: emplace_back

在向量:: emplace_back中就地构造std :: pair

POD结构的std :: vector :: emplace_back与分配的性能

带有 POD C++ 的 std::vector::emplace_back

make_unique和emplace_back的简单结构

push_back与emplace_back到std :: vector <std :: string>

std :: vector :: erase的MoveAssignable要求与std :: vector :: emplace_back的MoveInsertable要求

emplace_back无法与std :: vector <std :: map <int,int >>一起使用

具有已构建对象的std :: move与emplace_back()的C ++ 11 push_back()效率

将一对插入std :: vector时emplace_back()vs push_back

C ++-std :: initializer_list与std :: span

std :: vector emplace_back()用于不可复制的可构造对象

它发生了什么 = std::vector::end after emplace_back

可以从vector本身的元素构造std :: vector emplace_back吗?

C++17 中 std::vector::emplace_back 返回值的用例是什么?

如何将std :: vector :: emplace_back用于vector <vector <int>>?

从std :: deque线程并发调用emplace_back()和operator []()是否安全?

具有左值表达式的std :: vector :: emplace_back

返回引用时的std :: vector :: emplace_back错误(C ++ 17)

std :: emplace_back调用向量中其他对象的构造函数?