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

How to Correctly Initialize a Vector with Move-Only Types in C ?

DDD
DDDOriginal
2024-12-17 16:06:11898browse

How to Correctly Initialize a Vector with Move-Only Types in C  ?

Vector Initialization with Move-Only Types

Consider the following code, which aims to initialize a vector with std::unique_ptr instances:

#include <vector>
#include <memory>

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

However, this code triggers an error during compilation in GCC 4.7, as std::unique_ptr does not support copying, and the compiler attempts to create copies of the pointers during initialization.

GCC's Behavior

GCC's attempt to copy the pointers can be considered correct under the current C standard, which does not explicitly address list-initialization scenarios for move-only types like unique_ptr.

Alternative Initialization Methods

To properly initialize a vector with move-only types, one can employ the following approaches:

Using Iterators:

This approach involves creating a move iterator for the initializer list and passing it to the vector's constructor:

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

Using rref_wrapper:

This technique employs a helper type that provides a temporary storage for move references:

#include <utility>
#include <type_traits>

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&& _val;
};

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));
}

template<class T>
void rref(T&) = delete;

int main() {
  using move_only = std::unique_ptr<int>;
  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());
}

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

Statement:
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