说我有这个结构:
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
它只有一个构造函数。对于emplace
和emplace_back
功能也会出现相同的问题。将其可变参数模板参数转发给类的构造函数的几乎任何函数似乎都表现出这种行为。
我知道我可以通过以下方式解决此问题
positioned
两个int
参数的构造函数,并将{}
中的调用删除make_unique
,或make_unique
as position{1,2}
。在我看来,这两者似乎都太冗长了(在make_unique实现中付出了一些努力),这可以解决而无需参数类型的这种过分规范。
这是实现中可解决的缺陷,make_unique
还是一个没人要关心的无法解决,无趣的边缘情况?
当获得括号初始列表时,功能模板实参推导不起作用。它仅根据实际表达式起作用。
还应注意,无论如何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] 删除。
我来说两句