Why does stack<const string> not compile in g++? [duplicate] - c++

This question already has answers here:
Can I use const in vectors to allow adding elements, but not modifications to the already added?
(14 answers)
Does C++11 allow vector<const T>?
(5 answers)
Closed 6 years ago.
I encountered this problem maintaining a port for a large (relative to the size of our team) project, but it was simple to create a small example.
stackoverflow.cpp:
#include<iostream>
#include<string>
#include<stack>
using namespace std;
int main (int argc, char *argv[]) {
stack<const string> strstack;
string str("Hello, world");
strstack.push(str);
cout << strstack.top() << endl;
return 0;
}
Looks correct, right? MSVS thinks so too. However:
g++ stackoverflow.cpp
In file included from /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h:34:0,
from /usr/include/c++/4.7/bits/allocator.h:48,
from /usr/include/c++/4.7/string:43,
from /usr/include/c++/4.7/bits/locale_classes.h:42,
from /usr/include/c++/4.7/bits/ios_base.h:43,
from /usr/include/c++/4.7/ios:43,
from /usr/include/c++/4.7/ostream:40,
from /usr/include/c++/4.7/iostream:40,
from stackoverflow.cpp:1:
/usr/include/c++/4.7/ext/new_allocator.h: In instantiation of ‘class __gnu_cxx::new_allocator<const std::basic_string<char> >’:
/usr/include/c++/4.7/bits/allocator.h:89:11: required from ‘class std::allocator<const std::basic_string<char> >’
/usr/include/c++/4.7/bits/stl_deque.h:489:61: required from ‘class std::_Deque_base<const std::basic_string<char>, std::allocator<const std::basic_string<char> > >’
/usr/include/c++/4.7/bits/stl_deque.h:728:11: required from ‘class std::deque<const std::basic_string<char>, std::allocator<const std::basic_string<char> > >’
/usr/include/c++/4.7/bits/stl_stack.h:98:46: required from ‘class std::stack<const std::basic_string<char> >’
stackoverflow.cpp:9:23: required from here
/usr/include/c++/4.7/ext/new_allocator.h:83:7: error: ‘const _Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::const_reference) const [with _Tp = const std::basic_string<char>; __gnu_cxx::new_allocator<_Tp>::const_pointer = const std::basic_string<char>*; __gnu_cxx::new_allocator<_Tp>::const_reference = const std::basic_string<char>&]’ cannot be overloaded
/usr/include/c++/4.7/ext/new_allocator.h:79:7: error: with ‘_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = const std::basic_string<char>; __gnu_cxx::new_allocator<_Tp>::pointer = const std::basic_string<char>*; __gnu_cxx::new_allocator<_Tp>::reference = const std::basic_string<char>&]’
/usr/include/c++/4.7/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::deallocate(__gnu_cxx::new_allocator<_Tp>::pointer, __gnu_cxx::new_allocator<_Tp>::size_type) [with _Tp = const std::basic_string<char>; __gnu_cxx::new_allocator<_Tp>::pointer = const std::basic_string<char>*; __gnu_cxx::new_allocator<_Tp>::size_type = long unsigned int]’:
/usr/include/c++/4.7/bits/stl_deque.h:540:2: required from ‘void std::_Deque_base<_Tp, _Alloc>::_M_deallocate_node(_Tp*) [with _Tp = const std::basic_string<char>; _Alloc = std::allocator<const std::basic_string<char> >]’
/usr/include/c++/4.7/bits/stl_deque.h:643:2: required from ‘void std::_Deque_base<_Tp, _Alloc>::_M_destroy_nodes(_Tp**, _Tp**) [with _Tp = const std::basic_string<char>; _Alloc = std::allocator<const std::basic_string<char> >]’
/usr/include/c++/4.7/bits/stl_deque.h:566:4: required from ‘std::_Deque_base<_Tp, _Alloc>::~_Deque_base() [with _Tp = const std::basic_string<char>; _Alloc = std::allocator<const std::basic_string<char> >]’
/usr/include/c++/4.7/bits/stl_deque.h:781:15: required from ‘std::deque<_Tp, _Alloc>::deque() [with _Tp = const std::basic_string<char>; _Alloc = std::allocator<const std::basic_string<char> >]’
stackoverflow.cpp:9:23: required from here
/usr/include/c++/4.7/ext/new_allocator.h:100:9: error: invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
In file included from /usr/include/c++/4.7/ext/new_allocator.h:34:0,
from /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h:34,
from /usr/include/c++/4.7/bits/allocator.h:48,
from /usr/include/c++/4.7/string:43,
from /usr/include/c++/4.7/bits/locale_classes.h:42,
from /usr/include/c++/4.7/bits/ios_base.h:43,
from /usr/include/c++/4.7/ios:43,
from /usr/include/c++/4.7/ostream:40,
from /usr/include/c++/4.7/iostream:40,
from stackoverflow.cpp:1:
/usr/include/c++/4.7/new:97:6: error: initializing argument 1 of ‘void operator delete(void*)’ [-fpermissive]
In file included from /usr/include/c++/4.7/deque:63:0,
from /usr/include/c++/4.7/stack:61,
from stackoverflow.cpp:3:
/usr/include/c++/4.7/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, const _T2&) [with _T1 = const std::basic_string<char>; _T2 = std::basic_string<char>]’:
/usr/include/c++/4.7/bits/stl_uninitialized.h:77:3: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::_Deque_iterator<const std::basic_string<char>, const std::basic_string<char>&, const std::basic_string<char>*>; _ForwardIterator = std::_Deque_iterator<const std::basic_string<char>, const std::basic_string<char>&, const std::basic_string<char>*>; bool _TrivialValueTypes = false]’
/usr/include/c++/4.7/bits/stl_uninitialized.h:119:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::_Deque_iterator<const std::basic_string<char>, const std::basic_string<char>&, const std::basic_string<char>*>; _ForwardIterator = std::_Deque_iterator<const std::basic_string<char>, const std::basic_string<char>&, const std::basic_string<char>*>]’
/usr/include/c++/4.7/bits/stl_uninitialized.h:260:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::_Deque_iterator<const std::basic_string<char>, const std::basic_string<char>&, const std::basic_string<char>*>; _ForwardIterator = std::_Deque_iterator<const std::basic_string<char>, const std::basic_string<char>&, const std::basic_string<char>*>; _Tp = const std::basic_string<char>]’
/usr/include/c++/4.7/bits/stl_deque.h:841:9: required from ‘std::deque<_Tp, _Alloc>::deque(const std::deque<_Tp, _Alloc>&) [with _Tp = const std::basic_string<char>; _Alloc = std::allocator<const std::basic_string<char> >; std::deque<_Tp, _Alloc> = std::deque<const std::basic_string<char>, std::allocator<const std::basic_string<char> > >]’
/usr/include/c++/4.7/bits/stl_stack.h:130:14: required from ‘std::stack<_Tp, _Sequence>::stack(const _Sequence&) [with _Tp = const std::basic_string<char>; _Sequence = std::deque<const std::basic_string<char>, std::allocator<const std::basic_string<char> > >]’
stackoverflow.cpp:9:23: required from here
/usr/include/c++/4.7/bits/stl_construct.h:85:7: error: invalid static_cast from type ‘const std::basic_string<char>*’ to type ‘void*’
With stack<string> strstack; it's all clean. Is this a g++ bug? Is there a workaround so that we won't have to drop the const until the bug is fixed?

The members of a standard container have to be copy assignable or movable (C++11). If the type is const it fails the requirements.

It is possible for the container to hold pointers (or preferably, smart pointers) to constants. This maintains the desired const semantics, although perhaps the syntax is a bit more clunky.
For example:
stack<shared_ptr<string const>> s;
s.push(make_shared<string>("foo"));
cout << *s.top() << endl;
For more info see this question.

Related

Eigen: vector of linear system solver

I'm working with the Eigen linear algebra library and need a vector of BiCGSTAB-solvers. Unfortunately, extending this vector is extremely difficult. The minimal (not) working example is
#include <Eigen/Eigen>
int main() {
std::vector< Eigen::BiCGSTAB< Eigen::SparseMatrix< double > > > tmp;
tmp.emplace_back();
}
and yields the error message
$ g++ -I/usr/include/eigen3 main.cpp
In file included from /usr/include/c++/12.2.0/vector:63,
from /usr/include/c++/12.2.0/functional:62,
from /usr/include/eigen3/Eigen/Core:85,
from /usr/include/eigen3/Eigen/Dense:1,
from /usr/include/eigen3/Eigen/Eigen:1,
from main.cpp:1:
/usr/include/c++/12.2.0/bits/stl_uninitialized.h: In instantiation of ‘constexpr bool std::__check_constructible() [with _ValueType = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >&&]’:
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:182:4: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = move_iterator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*>; _ForwardIterator = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*]’
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:372:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, allocator<_Tp>&) [with _InputIterator = move_iterator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*>; _ForwardIterator = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >]’
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:397:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*; _ForwardIterator = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*; _Allocator = allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >]’
/usr/include/c++/12.2.0/bits/vector.tcc:487:3: required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(iterator, _Args&& ...) [with _Args = {}; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >; iterator = std::vector<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >::iterator]’
/usr/include/c++/12.2.0/bits/vector.tcc:123:21: required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {}; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >; reference = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >&]’
main.cpp:5:21: required from here
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:90:56: error: static assertion failed: result type must be constructible from input type
90 | static_assert(is_constructible<_ValueType, _Tp>::value,
| ^~~~~
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:90:56: note: ‘std::integral_constant<bool, false>::value’ evaluates to false
Trying to std::move is worse, i.e.
#include <Eigen/Eigen>
#include <utility>
int main() {
std::vector< Eigen::BiCGSTAB< Eigen::SparseMatrix< double > > > tmp;
Eigen::BiCGSTAB< Eigen::SparseMatrix< double > > solver;
tmp.push_back( std::move( solver ) );
}
leads to the error message
g++ -I/usr/include/eigen3 main.cpp
In file included from /usr/include/c++/12.2.0/x86_64-pc-linux-gnu/bits/c++allocator.h:33,
from /usr/include/c++/12.2.0/bits/allocator.h:46,
from /usr/include/c++/12.2.0/string:41,
from /usr/include/c++/12.2.0/bits/locale_classes.h:40,
from /usr/include/c++/12.2.0/bits/ios_base.h:41,
from /usr/include/c++/12.2.0/ios:42,
from /usr/include/c++/12.2.0/istream:38,
from /usr/include/c++/12.2.0/sstream:38,
from /usr/include/c++/12.2.0/complex:45,
from /usr/include/eigen3/Eigen/Core:50,
from /usr/include/eigen3/Eigen/Dense:1,
from /usr/include/eigen3/Eigen/Eigen:1,
from main.cpp:1:
/usr/include/c++/12.2.0/bits/new_allocator.h: In instantiation of ‘void std::__new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Args = {Eigen::BiCGSTAB<Eigen::SparseMatrix<double, 0, int>, Eigen::DiagonalPreconditioner<double> >}; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >]’:
/usr/include/c++/12.2.0/bits/alloc_traits.h:516:17: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(allocator_type&, _Up*, _Args&& ...) [with _Up = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Args = {Eigen::BiCGSTAB<Eigen::SparseMatrix<double, 0, int>, Eigen::DiagonalPreconditioner<double> >}; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; allocator_type = std::allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >]’
/usr/include/c++/12.2.0/bits/vector.tcc:117:30: required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {Eigen::BiCGSTAB<Eigen::SparseMatrix<double, 0, int>, Eigen::DiagonalPreconditioner<double> >}; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >; reference = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >&]’
/usr/include/c++/12.2.0/bits/stl_vector.h:1294:21: required from ‘void std::vector<_Tp, _Alloc>::push_back(value_type&&) [with _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >; value_type = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >]’
main.cpp:9:18: required from here
/usr/include/c++/12.2.0/bits/new_allocator.h:175:11: error: use of deleted function ‘Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >::BiCGSTAB(const Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >&)’
175 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/eigen3/Eigen/IterativeLinearSolvers:42,
from /usr/include/eigen3/Eigen/Sparse:31,
from /usr/include/eigen3/Eigen/Eigen:2:
/usr/include/eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h:158:7: note: ‘Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >::BiCGSTAB(const Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >&)’ is implicitly deleted because the default definition would be ill-formed:
158 | class BiCGSTAB : public IterativeSolverBase<BiCGSTAB<_MatrixType,_Preconditioner> >
| ^~~~~~~~
/usr/include/eigen3/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h:158:7: error: use of deleted function ‘Eigen::IterativeSolverBase<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >::IterativeSolverBase(const Eigen::IterativeSolverBase<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >&)’
In file included from /usr/include/eigen3/Eigen/IterativeLinearSolvers:38:
/usr/include/eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h:143:7: note: ‘Eigen::IterativeSolverBase<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >::IterativeSolverBase(const Eigen::IterativeSolverBase<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >&)’ is implicitly deleted because the default definition would be ill-formed:
143 | class IterativeSolverBase : public SparseSolverBase<Derived>
| ^~~~~~~~~~~~~~~~~~~
/usr/include/eigen3/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h:143:7: error: use of deleted function ‘Eigen::SparseSolverBase<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >::SparseSolverBase(const Eigen::SparseSolverBase<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >&)’
In file included from /usr/include/eigen3/Eigen/SparseCore:64,
from /usr/include/eigen3/Eigen/Sparse:26:
/usr/include/eigen3/Eigen/src/SparseCore/SparseSolverBase.h:67:7: note: ‘Eigen::SparseSolverBase<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >::SparseSolverBase(const Eigen::SparseSolverBase<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >&)’ is implicitly deleted because the default definition would be ill-formed:
67 | class SparseSolverBase : internal::noncopyable
| ^~~~~~~~~~~~~~~~
/usr/include/eigen3/Eigen/src/SparseCore/SparseSolverBase.h:67:7: error: ‘Eigen::internal::noncopyable::noncopyable(const Eigen::internal::noncopyable&)’ is private within this context
In file included from /usr/include/eigen3/Eigen/Core:162:
/usr/include/eigen3/Eigen/src/Core/util/Meta.h:424:21: note: declared private here
424 | EIGEN_DEVICE_FUNC noncopyable(const noncopyable&);
| ^~~~~~~~~~~
In file included from /usr/include/c++/12.2.0/vector:63,
from /usr/include/c++/12.2.0/functional:62,
from /usr/include/eigen3/Eigen/Core:85:
/usr/include/c++/12.2.0/bits/stl_uninitialized.h: In instantiation of ‘constexpr bool std::__check_constructible() [with _ValueType = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >&&]’:
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:182:4: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = move_iterator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*>; _ForwardIterator = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*]’
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:372:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, allocator<_Tp>&) [with _InputIterator = move_iterator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*>; _ForwardIterator = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >]’
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:397:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*; _ForwardIterator = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >*; _Allocator = allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >]’
/usr/include/c++/12.2.0/bits/vector.tcc:487:3: required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(iterator, _Args&& ...) [with _Args = {Eigen::BiCGSTAB<Eigen::SparseMatrix<double, 0, int>, Eigen::DiagonalPreconditioner<double> >}; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >; iterator = std::vector<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >::iterator]’
/usr/include/c++/12.2.0/bits/vector.tcc:123:21: required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {Eigen::BiCGSTAB<Eigen::SparseMatrix<double, 0, int>, Eigen::DiagonalPreconditioner<double> >}; _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >; reference = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >&]’
/usr/include/c++/12.2.0/bits/stl_vector.h:1294:21: required from ‘void std::vector<_Tp, _Alloc>::push_back(value_type&&) [with _Tp = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >; _Alloc = std::allocator<Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > >; value_type = Eigen::BiCGSTAB<Eigen::SparseMatrix<double> >]’
main.cpp:9:18: required from here
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:90:56: error: static assertion failed: result type must be constructible from input type
90 | static_assert(is_constructible<_ValueType, _Tp>::value,
| ^~~~~
/usr/include/c++/12.2.0/bits/stl_uninitialized.h:90:56: note: ‘std::integral_constant<bool, false>::value’ evaluates to false
I'm using Eigen 3.4 and g++ version 12.2.
Any ideas how to fix this?
Turning my comments into a proper answer:
After looking at the code, I found that BiCGSTAB like all solvers inherits from a base class designed to prevent copying, and by extension moving, too: class SparseSolverBase : internal::noncopyable
The exact reasons for this design choice I cannot tell. If I had to guess, I'd say some solvers probably use self-referential attributes (holding pointers to other members) which would break especially with fixed-size matrices. Or using Eigen::Map may cause issues on copy, especially copy-assignment.
std::vector only works with moveable types as it needs to move when it reallocates. Even when calling reserve() beforehand, the code still needs to compile, even if it is never executed.
Three workarounds come to mind:
Use std::deque. It provides a superset of all methods that vector has but its implementation means that as long as you only call emplace_back or emplace_front and not e.g. insert, it does not need moveable types. The downside is that it is a bit slower on all individual accesses
Use std::vector<std::unique_ptr<Solver>>. Less efficient than the deque but now you can also insert, reshuffle, etc.
Use std::unique_ptr<Solver[]> and use the good old new Solver[count] allocation. Starting with C++14, you can use std::make_unique<Solver[]>(count). This has the least overhead, even less than vector but the interface isn't as nice (you can use the [index] operator but the pointer doesn't even know the array size) and the number is fixed after allocation

How to insert elements of Enum type into vector of type uint8_t?

I am very new to C++ programming. I want to insert elements of type enum into a vector<uint8_t> ? ie append all elements of std::vector <ValType> call to std::vector<uint8_t> bravo .Is there any way to do so?
#include <stdio.h>
#include <vector>
#include <cstdint>
enum class ValType : uint8_t
{
Working = 1,
Failed = 0,
Freezed = 0
};
int main()
{
std::vector<uint8_t> bravo = {23, 23, 23, 22, 5};
std::vector<ValType> call;
bravo.insert(bravo.end(), call.begin(), call.end());
return 0;
}
Live Here
I am getting an error while compiling :
In file included from c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\vector:66,
from custom.cpp:2:
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_uninitialized.h: In instantiation of '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; _ForwardIterator = unsigned char*]':
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_uninitialized.h:333:37: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; _ForwardIterator = unsigned char*; _Tp = unsigned char]'
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\vector.tcc:751:34: required from 'void std::vector<_Tp, _Alloc>::_M_range_insert(std::vector<_Tp, _Alloc>::iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; _Tp = unsigned char; _Alloc = std::allocator<unsigned char>; std::vector<_Tp, _Alloc>::iterator = std::vector<unsigned char>::iterator]'
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_vector.h:1665:19: required from 'void std::vector<_Tp, _Alloc>::_M_insert_dispatch(std::vector<_Tp, _Alloc>::iterator, _InputIterator, _InputIterator, std::__false_type) [with _InputIterator = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; _Tp = unsigned char; _Alloc = std::allocator<unsigned char>; std::vector<_Tp, _Alloc>::iterator = std::vector<unsigned char>::iterator]'
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_vector.h:1383:22: required from 'std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::const_iterator, _InputIterator, _InputIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; <template-parameter-2-2> = void; _Tp = unsigned char; _Alloc = std::allocator<unsigned char>; std::vector<_Tp, _Alloc>::iterator = std::vector<unsigned char>::iterator; std::vector<_Tp, _Alloc>::const_iterator = std::vector<unsigned char>::const_iterator]'
custom.cpp:18:17: required from here
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_uninitialized.h:138:72: error: static assertion failed: result type must be constructible from value type of input range
138 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
| ^~~~~
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_uninitialized.h:138:72: note: 'std::integral_constant<bool, false>::value' evaluates to false
In file included from c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\vector:60,
from custom.cpp:2:
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_algobase.h: In instantiation of 'static _OI std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II = ValType*; _OI = unsigned char*]':
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_algobase.h:495:30: required from '_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = ValType*; _OI = unsigned char*]'
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_algobase.h:522:42: required from '_OI std::__copy_move_a1(_II, _II, _OI) [with bool _IsMove = false; _II = ValType*; _OI = unsigned char*]'
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_algobase.h:530:31: required from '_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; _OI = __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char> >]'
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_algobase.h:620:7: required from '_OI std::copy(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; _OI = __gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char> >]'
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\vector.tcc:744:16: required from 'void std::vector<_Tp, _Alloc>::_M_range_insert(std::vector<_Tp, _Alloc>::iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; _Tp = unsigned char; _Alloc = std::allocator<unsigned char>; std::vector<_Tp, _Alloc>::iterator = std::vector<unsigned char>::iterator]'
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_vector.h:1665:19: required from 'void std::vector<_Tp, _Alloc>::_M_insert_dispatch(std::vector<_Tp, _Alloc>::iterator, _InputIterator, _InputIterator, std::__false_type) [with _InputIterator = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; _Tp = unsigned char; _Alloc = std::allocator<unsigned char>; std::vector<_Tp, _Alloc>::iterator = std::vector<unsigned char>::iterator]'
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_vector.h:1383:22: required from 'std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::const_iterator, _InputIterator, _InputIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<ValType*, std::vector<ValType> >; <template-parameter-2-2> = void; _Tp = unsigned char; _Alloc = std::allocator<unsigned char>; std::vector<_Tp, _Alloc>::iterator = std::vector<unsigned char>::iterator; std::vector<_Tp, _Alloc>::const_iterator = std::vector<unsigned char>::const_iterator]'
custom.cpp:18:17: required from here
c:\program files (x86)\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\include\c++\11.2.0\bits\stl_algobase.h:385:25: error: cannot convert 'ValType' to 'unsigned char' in assignment
385 | *__result = *__first;
| ~~~~~~~~~~^~~~~~~~~~
Can someone please show me the correct way of doing this?
You can use std::transform with your own conversion function.
std::vector<uint8_t> bravo = {23, 23, 23, 22, 5};
std::vector<ValType> call;
std::transform(bravo.cbegin(), bravo.cend(), std::back_inserter(call),
[](uint8_t a) { return static_cast<ValType>(a); });
This is explained in e.g. this scope enumeration reference:
There are no implicit conversions from the values of a scoped enumerator to integral types, although static_cast may be used to obtain the numeric value of the enumerator.
[Emphasis mine]
So while it might look like inheritance when defining the enumeration, it's not. The type ValType is a completely separate type, which can't be converted to or from any other plain integer type, not even the one used as the enumeration base-type.
That means you can't simply copy from a vector of ValType elements to a vector of uint8_t elements. If you need to do such a copy you must implement your own conversion (using e.g. static_cast), perhaps using std::transform and an back insert iterator.

"<<" Cant convert types when using result of dict.find() in C++ [duplicate]

This question already has answers here:
error: no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘std::_List_iterator<int>’)
(4 answers)
Why should I not #include <bits/stdc++.h>?
(9 answers)
Closed 8 months ago.
I'm trying to make a program that converts text you put in to bigger ascii art text. I made a prototype and ran it, and I got this error
error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::iterator' {aka 'std::_Rb_tree<std::__cxx11::basic_string<char>, std::pair<const std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >, std::_Select1st<std::pair<const std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> > >, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> > > >::iterator'})
(The full error is way too large to put here)
I think it's because I'm using a very specific type that std::cout doesn't support. I've tried tons of different ways to convert it into a normal string, but all of the functions I've tried don't support it either.
Code:
#include <map>
#include <string>
#include <iostream>
#include <vector>
#include <bits/stdc++.h>
int main() {
std::map<std::string, std::string> bigabc = {{"A", " ||||| \n|| || \n||||||| \n|| ||"}, {"B", "|||||||\n| |\n||||||\n| |\n|||||||"}, {"C", "|||||||\n||\n||\n||\n|||||||"}};
std::string input;
std::cin >> input;
std::transform(input.begin(), input.end(), input.begin(), ::toupper);
std::vector<std::string> chars(input.begin(), input.end());
for (int pos = 0; pos < chars.size(); pos++) {
std::cout << bigabc.find(chars[pos]) << "\n\n";
}
}
I've been stuck on this for hours. Is there any way to make this work, or should I just rewrite my code entirely?
I tried using bigabc.at() instead and got this error:
In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/vector:66,
from asciisnake.cpp:4:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_uninitialized.h: In instantiation of '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; _ForwardIterator = std::__cxx11::basic_string<char>*]':
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_uninitialized.h:325:37: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; _ForwardIterator = std::__cxx11::basic_string<char>*; _Tp = std::__cxx11::basic_string<char>]'
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_vector.h:1585:33: required from 'void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; _Tp = std::__cxx11::basic_string<char>; _Alloc = std::allocator<std::__cxx11::basic_string<char> >]'
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_vector.h:657:23: required from 'std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; <template-parameter-2-2> = void; _Tp = std::__cxx11::basic_string<char>; _Alloc = std::allocator<std::__cxx11::basic_string<char> >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::__cxx11::basic_string<char> >]'
asciisnake.cpp:15:62: required from here
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_uninitialized.h:137:72: error: static assertion failed: result type must be constructible from value type of input range
137 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
|
Tried using const map, <char, string> and bigabc[chars[pos]] and got this error:
asciisnake.cpp: In function 'int main()':
asciisnake.cpp:20:23: error: no match for 'operator[]' (operand types are 'const std::map<char, std::__cxx11::basic_string<char> >' and '__gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char> >::value_type' {aka 'std::__cxx11::basic_string<char>'})
20 | cout << bigabc[chars[pos]] << "\n\n";
| ^
In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/map:61,
from asciisnake.cpp:1:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_map.h:492:7: note: candidate: 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = char; _Tp = std::__cxx11::basic_string<char>; _Compare = std::less<char>; _Alloc = std::allocator<std::pair<const char, std::__cxx11::basic_string<char> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::__cxx11::basic_string<char>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = char]'
492 | operator[](const key_type& __k)
| ^~~~~~~~
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_map.h:492:34: note: no known conversion for argument 1 from '__gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char> >::value_type' {aka 'std::__cxx11::basic_string<char>'} to 'const key_type&' {aka 'const char&'}
492 | operator[](const key_type& __k)
| ~~~~~~~~~~~~~~~~^~~
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_map.h:512:7: note: candidate: 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = char; _Tp = std::__cxx11::basic_string<char>; _Compare = std::less<char>; _Alloc = std::allocator<std::pair<const char, std::__cxx11::basic_string<char> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::__cxx11::basic_string<char>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = char]'
512 | operator[](key_type&& __k)
| ^~~~~~~~
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_map.h:512:29: note: no known conversion for argument 1 from '__gnu_cxx::__alloc_traits<std::allocator<std::__cxx11::basic_string<char> >, std::__cxx11::basic_string<char> >::value_type' {aka 'std::__cxx11::basic_string<char>'} to 'std::map<char, std::__cxx11::basic_string<char> >::key_type&&' {aka 'char&&'}
512 | operator[](key_type&& __k)
| ~~~~~~~~~~~^~~
In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/vector:66,
from asciisnake.cpp:4:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_uninitialized.h: In instantiation of '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; _ForwardIterator = std::__cxx11::basic_string<char>*]':
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_uninitialized.h:325:37: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; _ForwardIterator = std::__cxx11::basic_string<char>*; _Tp = std::__cxx11::basic_string<char>]'
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_vector.h:1585:33: required from 'void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; _Tp = std::__cxx11::basic_string<char>; _Alloc = std::allocator<std::__cxx11::basic_string<char> >]'
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_vector.h:657:23: required from 'std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; <template-parameter-2-2> = void; _Tp = std::__cxx11::basic_string<char>; _Alloc = std::allocator<std::__cxx11::basic_string<char> >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::__cxx11::basic_string<char> >]'
asciisnake.cpp:17:52: required from here
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/10.3.0/include/c++/bits/stl_uninitialized.h:137:72: error: static assertion failed: result type must be constructible from value type of input range
137 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
|
bigabc.find() will return an iterator pointing to the matching pair {"A","||......"}. You can use ->second to get the second string, and that will print fine.
Even easier, you can use the [] operator instead of find(): cout << bigabc[chars[pos]]; will print the matching 'big' string for chars[pos].

gcc compile error "binding ‘const s’ to reference of type ‘s&’ discards qualifiers" when using boost::container::static_vector in other container

When using boost::container::static_vector in another container such as std::vector, gcc is returning a compile error. The following test case reproduces the error:
#include <boost/container/static_vector.hpp>
#include <vector>
struct s
{
boost::container::static_vector<int,6> a;
};
int main()
{
std::vector<s> b;
b.resize(6);
}
Complied with g++ template_test2.cpp on Ubuntu Xenial results in the following error:
In file included from /usr/include/c++/5/bits/char_traits.h:39:0,
from /usr/include/c++/5/string:40,
from /usr/include/c++/5/stdexcept:39,
from /usr/include/boost/container/throw_exception.hpp:26,
from /usr/include/boost/container/new_allocator.hpp:24,
from /usr/include/boost/container/vector.hpp:28,
from /usr/include/boost/container/static_vector.hpp:25,
from template_test2.cpp:1:
/usr/include/c++/5/bits/stl_algobase.h: In instantiation of ‘typename __gnu_cxx::__enable_if<(! std::__is_scalar<_Tp>::__value), void>::__type std::__fill_a(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = s*; _Tp = s; typename __gnu_cxx::__enable_if<(! std::__is_scalar<_Tp>::__value), void>::__type = void]’:
/usr/include/c++/5/bits/stl_algobase.h:747:20: required from ‘void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = s*; _Tp = s]’
/usr/include/c++/5/bits/vector.tcc:469:14: required from ‘void std::vector<_Tp, _Alloc>::_M_fill_insert(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = s; _Alloc = std::allocator<s>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<s*, std::vector<s> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = s*; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = s]’
/usr/include/c++/5/bits/stl_vector.h:1073:23: required from ‘void std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = s; _Alloc = std::allocator<s>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<s*, std::vector<s> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = s*; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = s]’
/usr/include/c++/5/bits/stl_vector.h:716:10: required from ‘void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type, std::vector<_Tp, _Alloc>::value_type) [with _Tp = s; _Alloc = std::allocator<s>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = s]’
template_test2.cpp:12:11: required from here
/usr/include/c++/5/bits/stl_algobase.h:701:11: error: binding ‘const s’ to reference of type ‘s&’ discards qualifiers
*__first = __value;
This error only occurs if struct s contains a static vector. What is the cause of this error, and is there a workaround available?
It looks like the default copy assigment operator generated by compiler has signature
s& operator= (s&);
and your code fails in this line of fill algorithm (it is called somehow in resize method):
for (; __first != __last; ++__first)
*__first = __value; // <----- call operator=(s&) passing const s& object
because __value is const reference to s object and it cannot be passed as argument to
operator=(s&) (const object cannot be modified).
About generating default copy assignment operator for classes you can read here. There is something strange with implementation of static_vector that default copy assignment operator takes s& as argument instead of const s&.
To resolve this issue you can implement your own version of this operator:
s& operator = (const s& other) {
a = other.a;
return *this;
}

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

This question already has answers here:
Why does stack<const string> not compile in g++? [duplicate]
(2 answers)
Closed 9 years ago.
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?
You are violating the requirements for the elements stated by the class vector. An element must be CopyAssignable.
const int is not a valid type to put into any standard container since it is not assignable.