Home > Backend Development > C++ > How Can I Initialize a Vector with Move-Only Types in C ?

How Can I Initialize a Vector with Move-Only Types in C ?

Linda Hamilton
Release: 2025-01-01 08:55:09
Original
888 people have browsed it

How Can I Initialize a Vector with Move-Only Types in C  ?

Can Vector Initialization with Move-Only Types be Achieved?

The question arises when attempting to initialize a vector with unique pointers, a move-only type. When encountering code like this:

#include <vector>
#include <memory>

using move_only = std::unique_ptr<int>;
std::vector<move_only> v { move_only(), move_only(), move_only() };
Copy after login

GCC 4.7 endeavors to copy the unique pointers from the initializer list, resulting in a copy attempt that isn't permissible due to the move-only nature of std::unique_ptr.

GCC's Approach: Is it Flawed?

GCC's intention to copy the pointers is correct, considering that unique pointers are non-copyable. However, the method it employs, copying from the initializer list, triggers the deleted copy constructor.

Alternative Solution Using Make Move Iterator

To handle move-only types in vector initialization, a preferred approach involves utilizing make move iterators:

#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))};
}
Copy after login

The iterators obtained from make move iterators facilitate the movement of elements upon dereferencing, resolving the problem with copying.

Alternative Solution Using Template Wrappers

Another approach involves employing template wrappers with rvalue reference semantics:

// Helper type for converting rvalues to lvalues
template<class T>
struct rref_wrapper
{
  explicit rref_wrapper(T&& v)
    : _val(std::move(v)) {}

  explicit operator T() const{
    return T{ std::move(_val) };
  }

private:
  T&amp;&amp; _val;
};

// Helper function to convert rvalues to rref_wrappers
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));
}

// Helper function to delete lvalue references
template<class T>
void rref(T&amp;) = delete;
Copy after login

While this solution provides a way to conceptually convert rvalues to lvalues, it is crucial to exercise caution due to its volatility. A more concise initialization can be achieved through a two-step process:

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());
Copy after login

The above is the detailed content of How Can I Initialize a Vector with Move-Only Types in C ?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template