列表初始化可以与仅移动类型的向量一起使用吗?
使用仅移动类型初始化向量时列表初始化语法中,GCC 尝试将 unique_pointers 复制到向量中。此行为源于 unique_ptr 不可复制的事实。
GCC 尝试复制指针是否正确?
GCC 在这种情况下的行为不正确。 unique_ptrs 的向量不能通过复制指针来构造;相反,必须使用移动语义。
替代解决方案
要正确初始化仅移动类型的向量,有必要使用 std::make_move_iterator 来创建迭代器来移动指向的元素取消引用:
#include <iterator> #include <vector> #include <memory> int main() { using move_only = std::unique_ptr<int>; move_only init[] = { move_only(), move_only(), move_only() }; std::vector<move_only> v{std::make_move_iterator(std::begin(init)), std::make_move_iterator(std::end(init))}; }
其他方法
另一种替代方法,虽然不那么简单,但涉及使用 std::enable_if 和辅助结构 rref_wrapper 来构造移动向量-仅限类型:
#include <utility> #include <type_traits> template<class T> struct rref_wrapper { // CAUTION - very volatile, use with care explicit rref_wrapper(T&& v) : _val(std::move(v)) {} explicit operator T() const{ return T{ std::move(_val) }; } private: T&& _val; }; // only usable on temporaries template<class T> typename std::enable_if< !std::is_lvalue_reference<T>::value, rref_wrapper<T> >::type rref(T&& v){ return rref_wrapper<T>(std::move(v)); } // lvalue reference can go away template<class T> void rref(T&) = delete;
使用此助手,向量可以分两步初始化:
std::initializer_list<rref_wrapper<move_only>> il{ rref(move_only()), rref(move_only()), rref(move_only()) }; std::vector<move_only> v(il.begin(), il.end());
此方法利用 std::enable_if 来确保 rref 只能用于临时变量,从而防止任何潜在的误用。
以上是C 中列表初始化能否正确处理仅移动类型的向量?的详细内容。更多信息请关注PHP中文网其他相关文章!