如何解决如何在boost :: variant包装的指针容器中将原始指针更改为unique_ptr
我试图在向量中保留指向基类模板化版本的指针的变体。指针的boost::variant
恰好包含在结构中。如果这些指针是原始指针,则效果很好,但是当我将其更改为unique_ptr
时,事情就开始出错了。
struct Sayer {
struct Category {
using GetterVariant = boost::variant<
//Getter<string>*,// works OK
//Getter<double>*,// ...
//Getter<int>* // ...
unique_ptr<Getter<string>>,unique_ptr<Getter<double>>,unique_ptr<Getter<int>>
>;
Category(GetterVariant g) :
getter(g)
{}
GetterVariant getter;
};
vector<Category> categories;
template <typename G>
void addGetter() {
categories.emplace_back(new G()); // allocate here,transfer ownership to Sayer::categories
}
};
编译器错误:
/usr/include/boost/variant/variant.hpp:1627:28: error: no matching member
function for call to 'initialize'
initializer::initialize(
~~~~~~~~~~~~~^~~~~~~~~~
/usr/include/boost/variant/variant.hpp:1798:9: note: in instantiation of function
template specialization
'boost::variant<std::unique_ptr<Getter<std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::default_delete<Getter<std::__cxx11::basic_string<char,std::allocator<char> > > > >,std::unique_ptr<Getter<double>,std::default_delete<Getter<double> > >,std::unique_ptr<Getter<int>,std::default_delete<Getter<int> > >
>::convert_construct<AgeGetter *>' requested here
convert_construct( detail::variant::move(operand),1L);
...
main.cpp:54:16: note: in instantiation of function template specialization
'std::vector<Sayer::Category,std::allocator<Sayer::Category>
>::emplace_back<AgeGetter *>' requested here
categories.emplace_back(new G());
^
main.cpp:65:9: note: in instantiation of function template specialization
'Sayer::addGetter<AgeGetter>' requested here
sayer.addGetter<AgeGetter>();
...
/usr/include/boost/variant/detail/initializer.hpp:115:24: note: candidate
function not viable: no kNown conversion from 'typename
::boost::move_detail::remove_reference<AgeGetter *&>::type'
(aka 'AgeGetter *') to 'std::unique_ptr<Getter<int>,std::default_delete<Getter<int> > >' for 2nd argument
/usr/include/boost/variant/detail/initializer.hpp:149:17: note: candidate
function not viable: requires 0 arguments,but 2 were provided
static void initialize();
如何进行设置,以使内存所有权位于容器中?
解决方法
两件事:
首先,您必须在g
构造函数中移动Category
,因为如果某个变体的任何成员都是不可复制的,则该变体是不可复制的。
第二,虽然链AgeGetter*
到Getter<int>*
到std::unique_ptr<Getter<int>>
到Category
的每个转换都是隐式的,但是C ++仅执行有限数量的隐式转换。因此,基本上,此链太长了,您可以例如通过使用emplace_back(std::make_unique<G>())
而不是emplace_back(new G())
来修复它。
这也更安全,因为如果emplace_back
抛出(可以抛出),则new G()
不会被删除并因此泄漏。但是如果unique_ptr
抛出,将调用std::make_unique<G>()
返回的析构函数emplace_back
,因此不会泄漏。您应始终尝试避免在代码中使用原始的new
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。