Agregar un vector a un vector

Suponiendo que tengo 2 vectores estándar:

vector a; vector b; 

Digamos también que ambos tienen alrededor de 30 elementos.

  • ¿Cómo agrego el vector b al final del vector a?

La manera sucia sería iterar a través de b y agregar cada elemento a través del vector::push_back() , ¡aunque no me gustaría hacer eso!

 a.insert(a.end(), b.begin(), b.end()); 

o

 a.insert(std::end(a), std::begin(b), std::end(b)); 

La segunda variante es una solución más genéricamente aplicable, ya que b también podría ser una matriz. Sin embargo, requiere C ++ 11

 std::copy (b.begin(), b.end(), std::back_inserter(a)); 

Esto puede usarse en caso de que los elementos del vector a no tengan un operador de asignación (por ejemplo, un miembro const).

En todos los demás casos, esta solución es ineficaz en comparación con la solución de inserción anterior.

Mientras dice “el comstackdor puede reservar”, ¿por qué confiar en él? ¿Y qué hay de la detección automática de semántica de movimiento? ¿Y qué hay de todo lo que se repite del nombre del contenedor con el begin y el end ?

¿No querrías algo, ya sabes, más simple?

(Desplácese hacia abajo para llegar a la línea main )

 #include  #include  #include  #include  template struct can_reserve: std::false_type {}; template struct can_reserve,void>: std::true_type {}; template struct secret_enum { enum class type {}; }; template using SecretEnum = typename secret_enum::type; template using EnableFuncIf = typename std::enable_if< b, SecretEnum >::type; template using DisableFuncIf = EnableFuncIf< !b, -override_num >; template::value >... > void try_reserve( C& c, std::size_t n ) { c.reserve(n); } template::value >... > void try_reserve( C& c, std::size_t ) { } // do nothing template struct has_size_method:std::false_type {}; template struct has_size_method().size() ), decltype( std::declval().size() ) >::value>::type>:std::true_type {}; namespace adl_aux { using std::begin; using std::end; template auto adl_begin(C&&c)->decltype( begin(std::forward(c)) ); template auto adl_end(C&&c)->decltype( end(std::forward(c)) ); } template struct iterable_traits { typedef decltype( adl_aux::adl_begin(std::declval()) ) iterator; typedef decltype( adl_aux::adl_begin(std::declval()) ) const_iterator; }; template using Iterator = typename iterable_traits::iterator; template using ConstIterator = typename iterable_traits::const_iterator; template using IteratorCategory = typename std::iterator_traits::iterator_category; template::value, 1>... > std::size_t size_at_least( C&& c ) { return c.size(); } template::value && std::is_base_of< std::random_access_iterator_tag, IteratorCategory> >::value, 2>... > std::size_t size_at_least( C&& c ) { using std::begin; using std::end; return end(c)-begin(c); }; template::value && !std::is_base_of< std::random_access_iterator_tag, IteratorCategory> >::value, 3>... > std::size_t size_at_least( C&& c ) { return 0; }; template < typename It > auto try_make_move_iterator(It i, std::true_type) -> decltype(make_move_iterator(i)) { return make_move_iterator(i); } template < typename It > It try_make_move_iterator(It i, ...) { return i; } #include  template C1&& append_containers( C1&& c1, C2&& c2 ) { using std::begin; using std::end; try_reserve( c1, size_at_least(c1) + size_at_least(c2) ); using is_rvref = std::is_rvalue_reference; c1.insert( end(c1), try_make_move_iterator(begin(c2), is_rvref{}), try_make_move_iterator(end(c2), is_rvref{}) ); return std::forward(c1); } struct append_infix_op {} append; template struct append_on_right_op { LHS lhs; template LHS&& operator=( RHS&& rhs ) { return append_containers( std::forward(lhs), std::forward(rhs) ); } }; template append_on_right_op operator+( LHS&& lhs, append_infix_op ) { return { std::forward(lhs) }; } template typename std::remove_reference::type operator+( append_on_right_op&& lhs, RHS&& rhs ) { typename std::decay::type retval = std::forward(lhs.lhs); return append_containers( std::move(retval), std::forward(rhs) ); } template void print_container( C&& c ) { for( auto&& x:c ) std::cout << x << ","; std::cout << "\n"; }; int main() { std::vector a = {0,1,2}; std::vector b = {3,4,5}; print_container(a); print_container(b); a +append= b; const int arr[] = {6,7,8}; a +append= arr; print_container(a); print_container(b); std::vector d = ( std::vector{-3.14, -2, -1} +append= a ); print_container(d); std::vector c = std::move(d) +append+ a; print_container(c); print_container(d); std::vector e = c +append+ std::move(a); print_container(e); print_container(a); } 

jeje .

Ahora con move-data-from-rhs, append-array-to-container, append forward_list-to-container, move-container-from-lhs, gracias a la ayuda de @ DyP.

Tenga en cuenta que lo anterior no se comstack en clang gracias a la EnableFunctionIf<>... En clang, esta solución funciona.

Si desea agregar vector a sí mismo, fallarán ambas soluciones populares:

 std::vector v, orig; orig.push_back("first"); orig.push_back("second"); // BAD: v = orig; v.insert(v.end(), v.begin(), v.end()); // Now v contains: { "first", "second", "", "" } // BAD: v = orig; std::copy(v.begin(), v.end(), std::back_inserter(v)); // std::bad_alloc exception is generated // GOOD, but I can't guarantee it will work with any STL: v = orig; v.reserve(v.size()*2); v.insert(v.end(), v.begin(), v.end()); // Now v contains: { "first", "second", "first", "second" } // GOOD, but I can't guarantee it will work with any STL: v = orig; v.reserve(v.size()*2); std::copy(v.begin(), v.end(), std::back_inserter(v)); // Now v contains: { "first", "second", "first", "second" } // GOOD (best): v = orig; v.insert(v.end(), orig.begin(), orig.end()); // note: we use different vectors here // Now v contains: { "first", "second", "first", "second" }