Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I not call reserve on a vector of const elements? [duplicate]

Tags:

c++

vector

I have been told that it is good practice to call vector.reserve() before inserting a large amount of elements. I just came upon a situation where I want to put a large number of const elements into a vector. When calling reserve(), however, a compiler error is thrown.

Consider the following code reproducing the problem:

#include <vector>

int main()
{
    std::vector<const int> vec;
    vec.reserve(2);
}

This results in the following huge compiler error:

In file included from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++allocator.h:33:0,
                 from /usr/include/c++/4.8/bits/allocator.h:46,
                 from /usr/include/c++/4.8/vector:61,
                 from vecreserve.cpp:1:
/usr/include/c++/4.8/ext/new_allocator.h: In instantiation of ‘struct __gnu_cxx::new_allocator’:
/usr/include/c++/4.8/bits/allocator.h:92:11:   required from ‘class std::allocator’
/usr/include/c++/4.8/bits/alloc_traits.h:90:43:   required from ‘struct std::allocator_traits >’
/usr/include/c++/4.8/ext/alloc_traits.h:121:10:   required from ‘struct __gnu_cxx::__alloc_traits >’
/usr/include/c++/4.8/bits/stl_vector.h:75:28:   required from ‘struct std::_Vector_base >’
/usr/include/c++/4.8/bits/stl_vector.h:210:11:   required from ‘class std::vector’
vecreserve.cpp:5:26:   required from here
/usr/include/c++/4.8/ext/new_allocator.h:93:7: error: ‘const _Tp* __gnu_cxx::new_allocator::address(__gnu_cxx::new_allocator::const_reference) const [with _Tp = const int; __gnu_cxx::new_allocator::const_pointer = const int*; __gnu_cxx::new_allocator::const_reference = const int&]’ cannot be overloaded
       address(const_reference __x) const _GLIBCXX_NOEXCEPT
       ^
/usr/include/c++/4.8/ext/new_allocator.h:89:7: error: with ‘_Tp* __gnu_cxx::new_allocator::address(__gnu_cxx::new_allocator::reference) const [with _Tp = const int; __gnu_cxx::new_allocator::pointer = const int*; __gnu_cxx::new_allocator::reference = const int&]’
       address(reference __x) const _GLIBCXX_NOEXCEPT
       ^
/usr/include/c++/4.8/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator::deallocate(__gnu_cxx::new_allocator::pointer, __gnu_cxx::new_allocator::size_type) [with _Tp = const int; __gnu_cxx::new_allocator::pointer = const int*; __gnu_cxx::new_allocator::size_type = long unsigned int]’:
/usr/include/c++/4.8/bits/stl_vector.h:174:4:   required from ‘void std::_Vector_base::_M_deallocate(std::_Vector_base::pointer, std::size_t) [with _Tp = const int; _Alloc = std::allocator; std::_Vector_base::pointer = const int*; std::size_t = long unsigned int]’
/usr/include/c++/4.8/bits/vector.tcc:80:28:   required from ‘void std::vector::reserve(std::vector::size_type) [with _Tp = const int; _Alloc = std::allocator; std::vector::size_type = long unsigned int]’
vecreserve.cpp:6:16:   required from here
/usr/include/c++/4.8/ext/new_allocator.h:110:30: error: invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
       { ::operator delete(__p); }
                              ^
In file included from /usr/include/c++/4.8/ext/new_allocator.h:33:0,
                 from /usr/include/x86_64-linux-gnu/c++/4.8/bits/c++allocator.h:33,
                 from /usr/include/c++/4.8/bits/allocator.h:46,
                 from /usr/include/c++/4.8/vector:61,
                 from vecreserve.cpp:1:
/usr/include/c++/4.8/new:95:6: error:   initializing argument 1 of ‘void operator delete(void*)’ [-fpermissive]
 void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
      ^
In file included from /usr/include/c++/4.8/vector:60:0,
                 from vecreserve.cpp:1:
/usr/include/c++/4.8/bits/stl_algobase.h: In instantiation of ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = true; _II = const int*; _OI = const int*]’:
/usr/include/c++/4.8/bits/stl_algobase.h:428:38:   required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = true; _II = const int*; _OI = const int*]’
/usr/include/c++/4.8/bits/stl_algobase.h:460:17:   required from ‘_OI std::copy(_II, _II, _OI) [with _II = std::move_iterator; _OI = const int*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:93:53:   required from ‘static _ForwardIterator std::__uninitialized_copy::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = const int*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:117:41:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = const int*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:258:63:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator&) [with _InputIterator = std::move_iterator; _ForwardIterator = const int*; _Tp = const int]’
/usr/include/c++/4.8/bits/stl_vector.h:1142:29:   required from ‘std::vector::pointer std::vector::_M_allocate_and_copy(std::vector::size_type, _ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::move_iterator; _Tp = const int; _Alloc = std::allocator; std::vector::pointer = const int*; std::vector::size_type = long unsigned int]’
/usr/include/c++/4.8/bits/vector.tcc:75:70:   required from ‘void std::vector::reserve(std::vector::size_type) [with _Tp = const int; _Alloc = std::allocator; std::vector::size_type = long unsigned int]’
vecreserve.cpp:6:16:   required from here
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: error: no matching function for call to ‘std::__copy_move::__copy_m(const int*&, const int*&, const int*&)’
                        _Category>::__copy_m(__first, __last, __result);
                                                                      ^
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: note: candidate is:
/usr/include/c++/4.8/bits/stl_algobase.h:368:9: note: template static _Tp* std::__copy_move::__copy_m(const _Tp*, const _Tp*, _Tp*) [with _Tp = _Tp; bool _IsMove = true]
         __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result)
         ^
/usr/include/c++/4.8/bits/stl_algobase.h:368:9: note:   template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: note:   deduced conflicting types for parameter ‘_Tp’ (‘int’ and ‘const int’)
                        _Category>::__copy_m(__first, __last, __result);
                                                                      ^

Why does this happen? Should I not call reserve on a vector of const elements? If so, why not?

like image 675
Chris Avatar asked Sep 06 '13 07:09

Chris


People also ask

Does vector insert reserve?

If the allocated memory capacity in the vector is large enough to contain the new elements, no additional allocations for the vector are needed. So no, then it won't reserve memory.

Can you modify a const vector?

vector<const string>: Cannot change the values of the elements of this vector after they've been added.

Can you add to a const vector?

You can't put items into a const vector, the vectors state is the items it holds, and adding items to the vector modifies that state. If you want to append to a vector you must take in a non const ref.

What does reserve do vector?

vector::reserveIncrease the capacity of the vector (the total number of elements that the vector can hold without requiring reallocation) to a value that's greater or equal to new_cap .


1 Answers

You are violating the requirements for the elements stated by the class vector. An element must be CopyAssignable.

like image 52
Lorenzo Donati -- Codidact.com Avatar answered Sep 20 '22 10:09

Lorenzo Donati -- Codidact.com