是否有一种方便的方法来重新分配具有新拥有对象的unique_ptr
的值,而无需重新指定类型?
std::unique_ptr<int> foo;
// .... Later, once we actually have a value to store...
foo = std::make_unique<int>(my_cool_value);
当然int
不是太碍眼,但是foo::element_type
可能很长,或者在重构后会发生变化。
foo = std::make_unique<decltype(foo)::element_type>(value);
…但这是相当可怕的(foo::element_type
不工作,因为foo
不能在常量表达式中使用)。
理想情况下,std::unique_ptr
应该支持转发emplace
类方法:
foo.reassign(value);
这将释放旧的值,并且像std::vector::emplace
一样,原地构造新的拥有对象。
…但据我所知,没有什么比make_unique<decltype(foo)::element_type>
更简洁的了。
EDIT:为支持operator=
的类型重新赋值的最简洁的方法当然是使用operator=
:
*foo = value;`
…但是我不想依赖element_type
的可复制性(例如,我最初在尝试使用输入文件流时遇到了这个问题)。
将参数(或其引用)存储到具有模板化转换操作符的代理对象中,该操作符可以推断目标类型。一旦你推导出了这个对象,就构造这个新对象。
template<class... Args>
struct maker {
template<class T>
operator std::unique_ptr<T>() && {
return make<T>(std::index_sequence_for<Args...>());
}
std::tuple<Args...> args;
private:
template<class T, size_t ... Is>
std::unique_ptr<T> make(std::index_sequence<Is...>) {
return std::make_unique<T>(std::get<Is>(std::move(args))...);
}
};
template<class... Args>
auto maybe_make_unique_eventually(Args&&... args){
return maker<Args&&...>{std::forward_as_tuple(std::forward<Args>(args)...)};
}
它不是成员函数,但自由函数基本上可以实现以下功能:
template<typename T, typename D, typename...Args>
void TakeNew(std::unique_ptr<T,D>& up, Args&&... args)
{
up.reset(new T{std::forward<Args>(args)...});
// or use parentheses for consistency with `make_unique`; see comments
}
// usage...
auto foo = std::make_unique<int>(3);
// .... Later...
TakeNew(foo, 5);
(我认为这个解决方案并不理想)
#include <memory>
// a class with a long and unweildy name
namespace mary {
namespace poppins {
struct supercalafragalisticexpialadocious
{
};
}
}
int main()
{
// what we don't want to have to do:
auto a = std::make_unique<mary::poppins::supercalafragalisticexpialadocious>();
// so alias the typename
using atrocious = mary::poppins::supercalafragalisticexpialadocious;
// same type with a shorter name
a = std::make_unique<atrocious>();
}
因为你有唯一的所有权,除非类型是不可复制的,你可以简单地做
*foo = value;