home | help
std::ranges...construct_n(3)   C++ Standard Libary  std::ranges...construct_n(3)

NAME
     std::ranges::uninitialized_value_construct_n    -	 std::ranges::uninitial-
     ized_value_construct_n

Synopsis
	Defined in header <memory>
	Call signature
	template< no-throw-forward-iterator I >

	requires		std::default_initializable<std::iter_value_t<I>>
     (since C++20)

	I uninitialized_value_construct_n( I first, std::iter_difference_t<I>
	n );

	Constructs  n  objects of type std::iter_value_t<I> in the uninitialized
     memory area
	starting at first by value-initialization, as if by
	for (; n-- > 0; ++first)
	    ::new (static_cast<void*>(std::addressof(*first)))
		std::remove_reference_t<std::iter_reference_t<I>>();

	If an exception is thrown during the initialization, the objects already
     constructed
	are destroyed in an unspecified order.

	The function-like entities described on this page  are	niebloids,  that
     is:

	  *  Explicit  template  argument lists cannot be specified when calling
     any of them.
	  * None of them are visible to argument-dependent lookup.
	  * When any of them are found by normal unqualified lookup as the  name
     to the left
	    of	the  function-call operator, argument-dependent lookup is inhib-
     ited.

	In practice, they may be implemented as function objects, or  with  spe-
     cial compiler
	extensions.

Parameters
	first - the beginning of the range of elements to initialize
	n     - the number of elements to construct

Return value
	The end of the range of objects (i.e., ranges::next(first, n)).

Complexity
	Linear in n.

Exceptions
	The  exception thrown on construction of the elements in the destination
     range, if
	any.

Notes
	An implementation may improve the efficiency of the
	ranges::uninitialized_value_construct_n, e.g. by  using  ranges::fill_n,
     if the value
	type of the range is TrivialType and CopyAssignable.

Possible implementation
	struct uninitialized_value_construct_n_fn
	{
	    template<no-throw-forward-iterator I>
	    requires std::default_initializable<std::iter_value_t<I>>
	    I operator()(I first, std::iter_difference_t<I> n) const
	    {
		using T = std::remove_reference_t<std::iter_reference_t<I>>;
		if   constexpr	(std::is_trivial_v<T>  &&  std::is_copy_assigna-
     ble_v<T>)
		    return ranges::fill_n(first, n, T());
		I rollback{first};
		try
		{
		    for (; n-- > 0; ++first)
			::new	(const_cast<void*>(static_cast<const	volatile
     void*>
			    (std::addressof(*first)))) T();
		    return first;
		}
		catch (...) // rollback: destroy constructed elements
		{
		    for (; rollback != first; ++rollback)
			ranges::destroy_at(std::addressof(*rollback));
		    throw;
		}
	    }
	};

	inline	   constexpr	uninitialized_value_construct_n_fn    uninitial-
     ized_value_construct_n{};

Example
     // Run this code

      #include <iostream>
      #include <memory>
      #include <string>

      int main()
      {
	  struct S { std::string m{"aaaa aaaa aaaa "}; };

	  constexpr int n{4};
	  alignas(alignof(S)) char out[n * sizeof(S)];

	  try
	  {
	      auto first{reinterpret_cast<S*>(out)};
	      auto  last  =  std::ranges::uninitialized_value_construct_n(first,
     n);

	      auto count{1};
	      for (auto it{first}; it != last; ++it)
		  std::cout << count++ << ' ' << it->m << '\n';

	      std::ranges::destroy(first, last);
	  }
	  catch (...)
	  {
	      std::cout << "Exception!\n";
	  }

	  // Notice that for "trivial types" the uninitialized_value_construct_n
	  // zero-initializes the given uninitialized memory area.
	  int v[]{1, 2, 3, 4, 5, 6, 7, 8};
	  std::cout << ' ';
	  for (const int i : v)
	      std::cout << i << ' ';
	  std::cout << "\n ";
	  std::ranges::uninitialized_value_construct_n(std::begin(v),
     std::size(v));
	  for (const int i : v)
	      std::cout << i << ' ';
	  std::cout << '\n';
      }

Output:
      1 aaaa aaaa aaaa
      2 aaaa aaaa aaaa
      3 aaaa aaaa aaaa
      4 aaaa aaaa aaaa
      1 2 3 4 5 6 7 8
      0 0 0 0 0 0 0 0

	Defect reports

	The  following	behavior-changing  defect  reports were applied retroac-
     tively to
	previously published C++ standards.

	   DR	 Applied to		 Behavior as published		    Cor-
     rect behavior
	LWG 3870 C++20	    this algorithm might create objects on a const  kept
     disallowed
			    storage

See also
						  constructs objects  by  value-
     initialization
	ranges::uninitialized_value_construct	   in  an  uninitialized area of
     memory,
	(C++20) 				  defined by a range
						  (niebloid)
						  constructs objects by
	ranges::uninitialized_default_construct   default-initialization  in  an
     uninitialized
	(C++20) 				   area  of memory, defined by a
     range
						  (niebloid)
						  constructs objects by
	ranges::uninitialized_default_construct_n default-initialization  in  an
     uninitialized
	(C++20) 				   area  of memory, defined by a
     start and
						  count
						  (niebloid)
						  constructs objects  by  value-
     initialization
	uninitialized_value_construct_n 	   in  an  uninitialized area of
     memory,
	(C++17) 				  defined by a start and a count
						  (function template)

http://cppreference.com 	   2024.06.10	    std::ranges...construct_n(3)

home | help