Below is some code I wrote in c++.
ifstream objfile(s1.c_str());
string s2 = strfile;
std::istringstream objstr(s2);
if (path.empty()) objfile.set_rdbuf(objstr.rdbuf());
It has no problem compile in Visual Studio C++ 2017. When I try to compile using g++ in redhat linux, it has error
error: ‘std::ifstream’ has no member named ‘set_rdbuf’
Edit: Based on the initial answers to this question, I tried replacing the call to set_rdbuf with
objfile.rdbuf(objstr.rdbuf());
This still does not work. It says
rdbuf() const, note: candidate expects 0 arguments, 1 provided.
The full error messages is really long, I removed the lines of In files included from ...
error: no matching function for call to ‘std::basic_ifstream<char>::rdbuf(std::basic_istringstream<char>::__stringbuf_type*)’
if(path.empty()) objfile.rdbuf(objstr.rdbuf());
^
/usr/include/c++/4.8.2/fstream:509:7: note: std::basic_ifstream<_CharT, _Traits>::__filebuf_type* std::basic_ifstream<_CharT, _Traits>::rdbuf() const [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ifstream<_CharT, _Traits>::__filebuf_type = std::basic_filebuf<char>]
rdbuf() const
^
error: no matching function for call to ‘std::basic_ifstream<char>::rdbuf(std::basic_istringstream<char>::__stringbuf_type*)’
if (path.empty()) objfile.rdbuf(objstr.rdbuf());
^
/usr/include/c++/4.8.2/fstream:509:7: note: std::basic_ifstream<_CharT, _Traits>::__filebuf_type* std::basic_ifstream<_CharT, _Traits>::rdbuf() const [with _CharT = char; _Traits = std::char_traits<char>; std::basic_ifstream<_CharT, _Traits>::__filebuf_type = std::basic_filebuf<char>]
rdbuf() const
^
/usr/include/c++/4.8.2/fstream:509:7: note: candidate expects 0 arguments, 1 provided
/usr/include/c++/4.8.2/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::basic_istringstream<char>; _Args = {std::basic_istringstream<char, std::char_traits<char>, std::allocator<char> >}; _Tp = std::basic_istringstream<char>]’:
/usr/include/c++/4.8.2/bits/alloc_traits.h:254:4: required from ‘static typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::basic_istringstream<char>; _Args = {std::basic_istringstream<char, std::char_traits<char>, std::allocator<char> >}; _Alloc = std::allocator<std::basic_istringstream<char> >; typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type = void]’
/usr/include/c++/4.8.2/bits/alloc_traits.h:393:57: required from ‘static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::basic_istringstream<char>; _Args = {std::basic_istringstream<char, std::char_traits<char>, std::allocator<char> >}; _Alloc = std::allocator<std::basic_istringstream<char> >; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]’
/usr/include/c++/4.8.2/bits/vector.tcc:97:40: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {std::basic_istringstream<char, std::char_traits<char>, std::allocator<char> >}; _Tp = std::basic_istringstream<char>; _Alloc = std::allocator<std::basic_istringstream<char> >]’
/usr/include/c++/4.8.2/bits/stl_vector.h:920:36: required from ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::basic_istringstream<char>; _Alloc = std::allocator<std::basic_istringstream<char> >; std::vector<_Tp, _Alloc>::value_type = std::basic_istringstream<char>]’
/home/research/QZ/6_compile_Agency_Model/Agency_files/BondModel/utility.h:2413:37: required from here
/usr/include/c++/4.8.2/ext/new_allocator.h:120:4: error: use of deleted function ‘std::basic_istringstream<char>::basic_istringstream(const std::basic_istringstream<char>&)’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from /usr/include/c++/4.8.2/complex:45:0,
from /home/research/boost_library/boost_1_68_0/boost/detail/container_fwd.hpp:98,
from /home/research/boost_library/boost_1_68_0/boost/container_hash/extensions.hpp:22,
from /home/research/boost_library/boost_1_68_0/boost/container_hash/hash.hpp:760,
from /home/research/boost_library/boost_1_68_0/boost/type_index/stl_type_index.hpp:42,
from /home/research/boost_library/boost_1_68_0/boost/type_index.hpp:29,
from /home/research/boost_library/boost_1_68_0/boost/any.hpp:20,
from /home/research/boost_library/boost_1_68_0/boost/program_options/value_semantic.hpp:12,
from /home/research/boost_library/boost_1_68_0/boost/program_options/options_description.hpp:13,
/usr/include/c++/4.8.2/sstream:272:11: note: ‘std::basic_istringstream<char>::basic_istringstream(const std::basic_istringstream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
class basic_istringstream : public basic_istream<_CharT, _Traits>
^
/usr/include/c++/4.8.2/sstream:272:11: error: use of deleted function ‘std::basic_istream<char>::basic_istream(const std::basic_istream<char>&)’
/usr/include/c++/4.8.2/istream:58:11: note: ‘std::basic_istream<char>::basic_istream(const std::basic_istream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
class basic_istream : virtual public basic_ios<_CharT, _Traits>
^
/usr/include/c++/4.8.2/istream:58:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
/usr/include/c++/4.8.2/bits/basic_ios.h:66:11: note: ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’ is implicitly deleted because the default definition would be ill-formed:
class basic_ios : public ios_base
^
/usr/include/c++/4.8.2/bits/ios_base.h:786:5: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
ios_base(const ios_base&);
^
/usr/include/c++/4.8.2/bits/basic_ios.h:66:11: error: within this context
class basic_ios : public ios_base
^
/usr/include/c++/4.8.2/sstream:272:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
class basic_istringstream : public basic_istream<_CharT, _Traits>
^
/usr/include/c++/4.8.2/sstream:272:11: error: use of deleted function ‘std::basic_stringbuf<char>::basic_stringbuf(const std::basic_stringbuf<char>&)’
/usr/include/c++/4.8.2/sstream:64:11: note: ‘std::basic_stringbuf<char>::basic_stringbuf(const std::basic_stringbuf<char>&)’ is implicitly deleted because the default definition would be ill-formed:
class basic_stringbuf : public basic_streambuf<_CharT, _Traits>
^
/usr/include/c++/4.8.2/streambuf:802:7: error: ‘std::basic_streambuf<_CharT, _Traits>::basic_streambuf(const std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’ is private
basic_streambuf(const basic_streambuf& __sb)
^
/usr/include/c++/4.8.2/sstream:64:11: error: within this context
class basic_stringbuf : public basic_streambuf<_CharT, _Traits>
^
In file included from /usr/include/c++/4.8.2/vector:62:0,
/usr/include/c++/4.8.2/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::basic_istringstream<char>; _Args = {std::basic_istringstream<char, std::char_traits<char>, std::allocator<char> >}]’:
/usr/include/c++/4.8.2/bits/stl_uninitialized.h:75:53: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<std::basic_istringstream<char>*>; _ForwardIterator = std::basic_istringstream<char>*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.8.2/bits/stl_uninitialized.h:117:41: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<std::basic_istringstream<char>*>; _ForwardIterator = std::basic_istringstream<char>*]’
/usr/include/c++/4.8.2/bits/stl_uninitialized.h:258:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<std::basic_istringstream<char>*>; _ForwardIterator = std::basic_istringstream<char>*; _Tp = std::basic_istringstream<char>]’
/usr/include/c++/4.8.2/bits/stl_uninitialized.h:281:69: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = std::basic_istringstream<char>*; _ForwardIterator = std::basic_istringstream<char>*; _Allocator = std::allocator<std::basic_istringstream<char> >]’
/usr/include/c++/4.8.2/bits/vector.tcc:415:43: required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {std::basic_istringstream<char, std::char_traits<char>, std::allocator<char> >}; _Tp = std::basic_istringstream<char>; _Alloc = std::allocator<std::basic_istringstream<char> >]’
/usr/include/c++/4.8.2/bits/vector.tcc:101:54: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {std::basic_istringstream<char, std::char_traits<char>, std::allocator<char> >}; _Tp = std::basic_istringstream<char>; _Alloc = std::allocator<std::basic_istringstream<char> >]’
/usr/include/c++/4.8.2/bits/stl_vector.h:920:36: required from ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::basic_istringstream<char>; _Alloc = std::allocator<std::basic_istringstream<char> >; std::vector<_Tp, _Alloc>::value_type = std::basic_istringstream<char>]’
/home/research/QZ/6_compile_Agency_Model/Agency_files/BondModel/utility.h:2413:37: required from here
/usr/include/c++/4.8.2/bits/stl_construct.h:75:7: error: use of deleted function ‘std::basic_istringstream<char>::basic_istringstream(const std::basic_istringstream<char>&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
make[2]: *** [CMakeFiles/BondModel.dir/cashflowengine.cpp.o] Error 1
make[1]: *** [CMakeFiles/BondModel.dir/all] Error 2
This is quite interesting. As others have noted, the initial issue here is that the set_rdbuf member function is protected, so you can’t call it directly. I was surprised when you reported that calling the correct member function rdbuf didn’t compile, because that member function does exist and is public.
The short version is that I believe the following code will do what you want:
if (path.empty()) objfile.istream::rdbuf(objstr.rdbuf());
The reason you need the istream:: prefix here has to do with how C++ does name lookups in derived classes. If a derived class declares a member function with a given name and you try to call a function with that name, the compiler will not look to base classes to find potential overloads for that function. In C++11, the ifstream type had a new helper function added called rdbuf that returns the underlying buffer as a filebuf*. This shadows the istream function rdbuf that sets the underlying buffer. As a result, if call the one-argument version of rdbuf, C++ won’t find it because it stops searching as soon as it finds the zero-argument rdbuf defined in ifstream. Adding the explicit istream::rdbuf call tells the compiler to search for this function in istream first, where it ends up finding the function you want.
Hope this helps!
std::ifstream::set_rdbuf is protected, as mentioned here. It's possible that MSVC exposes it as a public member function in std::ifstream which would explain why your code compiles there.
What you want is rdbuf:
std::basic_streambuf<CharT, Traits>* rdbuf( std::basic_streambuf<CharT, Traits>* sb );
Sets the associated stream buffer to sb. The error state is cleared by calling clear(). Returns the associated stream buffer before the operation. If there is no associated stream buffer, returns a null pointer.
set_rdbuf is a protected member function. That is why it is not accessible.
Related
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
I'm trying to use the ExprTk mathematical expression parser library within a class whose objects are to be stored in a vector of objects, which is a member variable of another class; however, when I try to push_back a new object in the vector I'm getting a lot of "use of deleted function" errors. Here is a simple version of the code that is giving me problems:
#include <exprtk.hpp>
#include <iostream>
#include <string>
#include <vector>
class B {
public:
double x;
exprtk::symbol_table<double> symbol_table;
exprtk::parser<double> parser;
exprtk::expression<double> expr_obj;
B();
};
class A {
public:
std::vector<B> Bvec;
A();
};
A::A() {
Bvec.push_back(B());
};
B::B() {
symbol_table.add_variable("x", x);
expr_obj.register_symbol_table(symbol_table);
parser.compile("x^2",expr_obj);
x = 2.0;
std::cout << expr_obj.value() << std::endl;
}
int main(int argc, char const* argv[]) {
A a_obj;
return 0;
}
I haven't included the header library since it's nearly 40,000 lines, but it can be found here: http://www.partow.net/programming/exprtk/.
Here is the error message
In file included from /usr/include/x86_64-linux-gnu/c++/7/bits/c++allocator.h:33:0,
from /usr/include/c++/7/bits/allocator.h:46,
from /usr/include/c++/7/string:41,
from /usr/include/c++/7/bits/locale_classes.h:40,
from /usr/include/c++/7/bits/ios_base.h:41,
from /usr/include/c++/7/ios:42,
from /usr/include/c++/7/ostream:38,
from /usr/include/c++/7/iostream:39,
from src/main.cpp:1:
/usr/include/c++/7/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = B; _Args = {B}; _Tp = B]’:
/usr/include/c++/7/bits/alloc_traits.h:475:4: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = B; _Args = {B}; _Tp = B; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<B>]’
/usr/include/c++/7/bits/vector.tcc:100:30: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {B}; _Tp = B; _Alloc = std::allocator<B>]’
/usr/include/c++/7/bits/stl_vector.h:954:21: required from ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = B; _Alloc = std::allocator<B>; std::vector<_Tp, _Alloc>::value_type = B]’
src/main.cpp:25:21: required from here
/usr/include/c++/7/ext/new_allocator.h:136:4: error: use of deleted function ‘B::B(B&&)’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.cpp:6:7: note: ‘B::B(B&&)’ is implicitly deleted because the default definition would be ill-formed:
class B {
^
src/main.cpp:6:7: error: ‘exprtk::parser<T>::parser(const exprtk::parser<T>&) [with T = double]’ is private within this context
In file included from src/main.cpp:3:0:
ext_libs/exprtk/exprtk.hpp:35289:7: note: declared private here
parser(const parser<T>&);
^~~~~~
In file included from /usr/include/c++/7/bits/stl_tempbuf.h:60:0,
from /usr/include/c++/7/bits/stl_algo.h:62,
from /usr/include/c++/7/algorithm:62,
from ext_libs/exprtk/exprtk.hpp:37,
from src/main.cpp:3:
/usr/include/c++/7/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = B; _Args = {B}]’:
/usr/include/c++/7/bits/stl_uninitialized.h:83:18: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<B*>; _ForwardIterator = B*; bool _TrivialValueTypes = false]’
/usr/include/c++/7/bits/stl_uninitialized.h:134:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<B*>; _ForwardIterator = B*]’
/usr/include/c++/7/bits/stl_uninitialized.h:289:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<B*>; _ForwardIterator = B*; _Tp = B]’
/usr/include/c++/7/bits/stl_uninitialized.h:311:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = B*; _ForwardIterator = B*; _Allocator = std::allocator<B>]’
/usr/include/c++/7/bits/vector.tcc:426:6: required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {B}; _Tp = B; _Alloc = std::allocator<B>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<B*, std::vector<B> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = B*]’
/usr/include/c++/7/bits/vector.tcc:105:21: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {B}; _Tp = B; _Alloc = std::allocator<B>]’
/usr/include/c++/7/bits/stl_vector.h:954:21: required from ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = B; _Alloc = std::allocator<B>; std::vector<_Tp, _Alloc>::value_type = B]’
src/main.cpp:25:21: required from here
/usr/include/c++/7/bits/stl_construct.h:75:7: error: use of deleted function ‘B::B(B&&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Makefile:29: recipe for target 'obj/src/main.o' failed
make: *** [obj/src/main.o] Error 1
I'm pretty sure the issue has something to do with the push_back function and how the object is being copied; however, that's a bit over my head and knowledge of c++ (which is rather basic).
Any help would be appreciated. Thanks!
Looking at the ExprTk documentation (readme.txt), specifically Section 10.3 we have the following note:
Note: The exprtk::parser is a non-copyable and non-thread safe
component, and should only be shared via either a reference, a shared
pointer or a std::ref mechanism, and considerations relating to
synchronisation taken into account where appropriate. The parser
represents an object factory, specifically a factory of expressions,
and generally should not be instantiated solely on a per expression
compilation basis.
Section 10.3
parser cannot be copied, and based on the signature of how copying was prevented, the copy constructor was made private, it's unlikely that it can be moved either (private copy constructers were what you used before the disabling of a special member function with the delete keyword was added to the language in C++11, the same time move semantics were added). You cannot have a exprtk::parser instance as a member of an object you want to copy (unless you're going to get really weird in custom special member functions and NOT copy the exprtk::parser).
This is all enforcement of you not wanting to have multiple instance of the same Parser floating around. You will have to use a reference, most likely a smart pointer because references are a <expletive deleted> to copy assign, to a single instance instead.
But this raises the question of whether you need to keep parser around as a member at all. What about something like this:
class B {
public:
double x; // Not sure we need even this.
double result;
B();
};
B::B():
{
// parser is handled with local variables.
exprtk::symbol_table<double> symbol_table;
exprtk::parser<double> parser;
exprtk::expression<double> expr_obj;
symbol_table.add_variable("x", x);
expr_obj.register_symbol_table(symbol_table);
parser.compile("x^2",expr_obj);
x = 2.0;
result = expr_obj.value(); // store instead of printing
} // parser and friends are no longer needed and discarded.
I'm trying to do a Thread calling the cook class through a vector but I don't know to do it correctly. Here is my code:
for (int i = 0; i < _numCooks; i++) {
std::thread threadObj(this->_cooks[i].nextOrder, void);
_threads.push_back(threadObj);
}
_cooks is a vector of a class and the function that I am trying to make a thread of is:
bool cooks::nextOrder()
{
Margarita margarita(_cookOrder[0].pizzaSize);
Regina regina(_cookOrder[0].pizzaSize);
Fantasia fantasia(_cookOrder[0].pizzaSize);
Americana americana(_cookOrder[0].pizzaSize);
if (_cookOrder.empty())
return (false);
switch (_cookOrder[0].pizzaType) {
case plazza::Margarita:
return (makeOrder(margarita));
break;
case plazza::Regina:
return (makeOrder(regina));
break;
case plazza::Fantasia:
return (makeOrder(fantasia));
break;
case plazza::Americana:
return (makeOrder(americana));
break;
default:
return (false);
}
}
however when I try to compile I get this:
kitchen/kitchen.cpp: In member function ‘void
Kitchen::make_pizza(std::__cxx11::string, std::__cxx11::string, Ipc)’:
kitchen/kitchen.cpp:148:59: error: expected primary-expression before
‘void’
std::thread threadObj(this->_cooks[i].nextOrder, void);
^~~~ kitchen/kitchen.cpp:148:63: error: invalid use of non-static member
function ‘bool cooks::nextOrder()’
std::thread threadObj(this->_cooks[i].nextOrder, void);
^ In file included from kitchen/kitchen.hpp:17,
from kitchen/kitchen.cpp:5: kitchen/cooks.hpp:32:10: note: declared here
bool nextOrder();
^~~~~~~~~ In file included from /usr/include/c++/8/x86_64-redhat-linux/bits/c++allocator.h:33,
from /usr/include/c++/8/bits/allocator.h:46,
from /usr/include/c++/8/string:41,
from /usr/include/c++/8/bits/locale_classes.h:40,
from /usr/include/c++/8/bits/ios_base.h:41,
from /usr/include/c++/8/ios:42,
from /usr/include/c++/8/ostream:38,
from /usr/include/c++/8/iostream:39,
from kitchen/../pizza/IPizza.hpp:23,
from kitchen/../pizza/APizza.hpp:11,
from kitchen/kitchen.hpp:8,
from kitchen/kitchen.cpp:5: /usr/include/c++/8/ext/new_allocator.h: In instantiation of ‘void
__gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = cooks; _Args = {const cooks&}; _Tp = cooks]’: /usr/include/c++/8/bits/alloc_traits.h:475:4: required from ‘static
void std::allocator_traits
::construct(std::allocator_traits >::allocator_type&, _Up*, _Args&& ...) [with _Up = cooks; _Args = {const cooks&}; _Tp = cooks;
std::allocator_traits >::allocator_type =
std::allocator]’ /usr/include/c++/8/bits/stl_vector.h:1079:30:
required from ‘void std::vector<_Tp, _Alloc>::push_back(const
value_type&) [with _Tp = cooks; _Alloc = std::allocator;
std::vector<_Tp, _Alloc>::value_type = cooks]’
kitchen/kitchen.cpp:36:30: required from here
/usr/include/c++/8/ext/new_allocator.h:136:4: error: use of deleted
function ‘cooks::cooks(const cooks&)’ { ::new((void )__p)
_Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from kitchen/kitchen.hpp:17,
from kitchen/kitchen.cpp:5: kitchen/cooks.hpp:21:7: note: ‘cooks::cooks(const cooks&)’ is implicitly deleted because the
default definition would be ill-formed: class cooks
^~~~~ kitchen/cooks.hpp:21:7: error: use of deleted function ‘std::basic_ofstream<_CharT, _Traits>::basic_ofstream(const
std::basic_ofstream<_CharT, _Traits>&) [with _CharT = char; _Traits =
std::char_traits]’ In file included from
kitchen/../plazza.hpp:15,
from kitchen/kitchen.hpp:13,
from kitchen/kitchen.cpp:5: /usr/include/c++/8/fstream:778:7: note: declared here
basic_ofstream(const basic_ofstream&) = delete;
^~~~~~~~~~~~~~ In file included from /usr/include/c++/8/vector:62,
from kitchen/../pizza/IPizza.hpp:24,
from kitchen/../pizza/APizza.hpp:11,
from kitchen/kitchen.hpp:8,
from kitchen/kitchen.cpp:5: /usr/include/c++/8/bits/stl_construct.h: In instantiation of ‘void
std::_Construct(_T1, _Args&& ...) [with _T1 = cooks; _Args =
{cooks}]’: /usr/include/c++/8/bits/stl_uninitialized.h:83:18:
required from ‘static _ForwardIterator
std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = cooks*; bool
_TrivialValueTypes = false]’ /usr/include/c++/8/bits/stl_uninitialized.h:134:15: required from
‘_ForwardIterator std::uninitialized_copy(_InputIterator,
_InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator; _ForwardIterator = cooks*]’
/usr/include/c++/8/bits/stl_uninitialized.h:289:37: required from
‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator,
_InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator; _ForwardIterator = cooks*; _Tp = cooks]’
/usr/include/c++/8/bits/stl_uninitialized.h:311:2: required from
‘_ForwardIterator
std::__uninitialized_move_if_noexcept_a(_InputIterator,
_InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = cooks*; _ForwardIterator = cooks*; _Allocator =
std::allocator]’ /usr/include/c++/8/bits/vector.tcc:447:6:
required from ‘void std::vector<_Tp,
_Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const cooks&}; _Tp = cooks; _Alloc =
std::allocator; std::vector<_Tp, _Alloc>::iterator =
__gnu_cxx::__normal_iterator >; typename std::_Vector_base<_Tp, _Alloc>::pointer = cooks*]’
/usr/include/c++/8/bits/stl_vector.h:1085:4: required from ‘void
std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp =
cooks; _Alloc = std::allocator; std::vector<_Tp,
_Alloc>::value_type = cooks]’ kitchen/kitchen.cpp:36:30: required from here /usr/include/c++/8/bits/stl_construct.h:75:7: error: use of
deleted function ‘cooks::cooks(const cooks&)’
{ ::new(static_cast(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
make: *** [: kitchen/kitchen.o] Error 1
Is there any way to fix it?
According to this, the first argument to a std::thread constructor should meet the Callable concept. You then pass the subsequent arguments for the Callable as additional arguments to the constructor.
You're passing a member function. You need an instance of the class to call the method on, which you're not providing. This is what this error should mean to you.
error: invalid use of non-static member function ‘bool cooks::nextOrder()’
It's probably easiest to use a lambda ie.
for (int i = 0; i < _numCooks; i++) {
_threads.emplace_back([&cook = _cooks[i]]() {
cook.nextOrder();
});
}
I have the following code:
#include <string>
#include <vector>
struct S {
const std::string str;
};
int main() {
std::vector<S> v;
const std::string test("test");
S s;
v.push_back(s);
}
It compiles fine with g++ 4.8.5:
$ g++ --version
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
But when I tried to compile it with g++ 4.6.2, I got the following errors:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/vector:70:0,
from compilerTest.cpp:2:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const S&}, _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>::_Tp_alloc_type::pointer = S*]’:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_vector.h:834:4: instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = S, _Alloc = std::allocator<S>, std::vector<_Tp, _Alloc>::value_type = S]’
compilerTest.cpp:12:14: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:319:4: error: use of deleted function ‘S& S::operator=(const S&)’
compilerTest.cpp:4:8: error: ‘S& S::operator=(const S&)’ is implicitly deleted because the default definition would be ill-formed:
compilerTest.cpp:4:8: error: passing ‘const string {aka const std::basic_string<char>}’ as ‘this’ argument of ‘std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>]’ discards qualifiers [-fpermissive]
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/char_traits.h:41:0,
from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/string:42,
from compilerTest.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h: In static member function ‘static _BI2 std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1 = S*, _BI2 = S*]’:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:581:18: instantiated from ‘_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = S*, _BI2 = S*]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:590:34: instantiated from ‘_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = S*, _BI2 = S*]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:661:15: instantiated from ‘_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1 = S*, _BI2 = S*]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:313:4: instantiated from ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const S&}, _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>::_Tp_alloc_type::pointer = S*]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_vector.h:834:4: instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = S, _Alloc = std::allocator<S>, std::vector<_Tp, _Alloc>::value_type = S]’
compilerTest.cpp:12:14: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:546:6: error: use of deleted function ‘S& S::operator=(const S&)’
Why S& S::operator=(const S&) is "deleted"?
I was using the command to compile:
g++ -Wall compilerTest.cpp -o compilerTest -std=c++0x
Even I uses emplace_back(), it gives me similar error:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/x86_64-redhat-linux/bits/c++allocator.h:34:0,
from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/allocator.h:48,
from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/string:43,
from compilerTest.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/ext/new_allocator.h: In member function ‘void __gnu_cxx::new_allocator<_Tp>::construct(__gnu_cxx::new_allocator<_Tp>::pointer, _Args&& ...) [with _Args = {std::basic_string<char>&}, _Tp = S, __gnu_cxx::new_allocator<_Tp>::pointer = S*]’:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:97:6: instantiated from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {std::basic_string<char>&}, _Tp = S, _Alloc = std::allocator<S>]’
compilerTest.cpp:11:18: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/ext/new_allocator.h:114:4: error: no matching function for call to ‘S::S(std::basic_string<char>&)’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/ext/new_allocator.h:114:4: note: candidates are:
compilerTest.cpp:4:8: note: S::S()
compilerTest.cpp:4:8: note: candidate expects 0 arguments, 1 provided
compilerTest.cpp:4:8: note: S::S(const S&)
compilerTest.cpp:4:8: note: no known conversion for argument 1 from ‘std::basic_string<char>’ to ‘const S&’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/vector:70:0,
from compilerTest.cpp:2:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {std::basic_string<char>&}, _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>::_Tp_alloc_type::pointer = S*]’:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:102:4: instantiated from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {std::basic_string<char>&}, _Tp = S, _Alloc = std::allocator<S>]’
compilerTest.cpp:11:18: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:319:4: error: no matching function for call to ‘S::S(std::basic_string<char>&)’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:319:4: note: candidates are:
compilerTest.cpp:4:8: note: S::S()
compilerTest.cpp:4:8: note: candidate expects 0 arguments, 1 provided
compilerTest.cpp:4:8: note: S::S(const S&)
compilerTest.cpp:4:8: note: no known conversion for argument 1 from ‘std::basic_string<char>’ to ‘const S&’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/char_traits.h:41:0,
from /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/string:42,
from compilerTest.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h: In static member function ‘static _BI2 std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1 = S*, _BI2 = S*]’:
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:581:18: instantiated from ‘_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = S*, _BI2 = S*]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:590:34: instantiated from ‘_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = true, _BI1 = S*, _BI2 = S*]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:661:15: instantiated from ‘_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1 = S*, _BI2 = S*]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:313:4: instantiated from ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {std::basic_string<char>&}, _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>::_Tp_alloc_type::pointer = S*]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/vector.tcc:102:4: instantiated from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {std::basic_string<char>&}, _Tp = S, _Alloc = std::allocator<S>]’
compilerTest.cpp:11:18: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../include/c++/4.6.2/bits/stl_algobase.h:546:6: error: use of deleted function ‘S& S::operator=(const S&)’
compilerTest.cpp:4:8: error: ‘S& S::operator=(const S&)’ is implicitly deleted because the default definition would be ill-formed:
compilerTest.cpp:4:8: error: passing ‘const string {aka const std::basic_string<char>}’ as ‘this’ argument of ‘std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>]’ discards qualifiers [-fpermissive]
Why S& S::operator=(const S&) is "deleted"?
Because S has a const member str which makes the defaulted copy assignment operator is defined as deleted.
A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:
T has a non-static data member or a direct or virtual base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function);
It's impossible to call operator= on a const string, it's a non-const member function.
And the type requirements of std::vector changed from C++11:
T must meet the requirements of CopyAssignable and CopyConstructible.
(until C++11)
The requirements that are imposed on the elements depend on the actual
operations performed on the container. Generally, it is required that
element type is a complete type and meets the requirements of
Erasable, but many member functions impose stricter requirements.
(since C++11)
So from C++11 the requirment depends on the operation you performed. In fact, std::vector::push_back doesn't need type T to be CopyAssignable, CopyInsertable would be fine.
Type requirements
- T must meet the requirements of CopyInsertable in order to use overload (1).
That's why it compiles with gcc4.8.5, but gcc4.6.2 complains the copy assignment operator is deleted. (AFAIK gcc supported C++11 from 4.8.1)
Copy assignment is implicitly deleted when you have a non static const member
That's because the object that you copy into is not re-initialized, so you have an existing const that you can't reassign into.
In your case there's not full support of C++11, which requires vector members to have copy assignment
I'm using such field:
std::vector<OneItemIndex> oneItemIndexes;
This is part of OneItemIndex declaration:
class OneItemIndex : public CustomIndex
{
public:
OneItemIndex(int instrumentId_);
~OneItemIndex(void);
OneItemIndex(OneItemIndex& rhs);
...
In VC++ this compiles just fine, but in gcc I receive such compilation error:
In file included from /usr/include/c++/4.8/vector:62:0,
from ../IndexesStorage.h:4,
from ../IndexesStorage.cpp:1:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = OneItemIndex; _Args = {OneItemIndex}]’:
/usr/include/c++/4.8/bits/stl_uninitialized.h:75:53: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<OneItemIndex*>; _ForwardIterator = OneItemIndex*; bool _TrivialValueTypes = false]’
/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<OneItemIndex*>; _ForwardIterator = OneItemIndex*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:258:63: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<OneItemIndex*>; _ForwardIterator = OneItemIndex*; _Tp = OneItemIndex]’
/usr/include/c++/4.8/bits/stl_vector.h:1142:29: required from ‘std::vector<_Tp, _Alloc>::pointer std::vector<_Tp, _Alloc>::_M_allocate_and_copy(std::vector<_Tp, _Alloc>::size_type, _ForwardIterator, _ForwardIterator) [with _ForwardIterator = std::move_iterator<OneItemIndex*>; _Tp = OneItemIndex; _Alloc = std::allocator<OneItemIndex>; std::vector<_Tp, _Alloc>::pointer = OneItemIndex*; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/4.8/bits/vector.tcc:75:70: required from ‘void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = OneItemIndex; _Alloc = std::allocator<OneItemIndex>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]’
../IndexesStorage.cpp:197:55: required from here
/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: no matching function for call to ‘OneItemIndex::OneItemIndex(OneItemIndex)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
/usr/include/c++/4.8/bits/stl_construct.h:75:7: note: candidates are:
In file included from ../IndexesStorage.h:7:0,
from ../IndexesStorage.cpp:1:
../OneItemIndex.h:13:2: note: OneItemIndex::OneItemIndex(OneItemIndex&)
OneItemIndex(OneItemIndex& rhs);
^
../OneItemIndex.h:13:2: note: no known conversion for argument 1 from ‘OneItemIndex’ to ‘OneItemIndex&’
../OneItemIndex.h:8:2: note: OneItemIndex::OneItemIndex(int)
OneItemIndex(int instrumentId_);
^
../OneItemIndex.h:8:2: note: no known conversion for argument 1 from ‘OneItemIndex’ to ‘int’
Why gcc asks for OneItemIndex::OneItemIndex(OneItemIndex)? Should I add such construction, how to implement it?
Change
OneItemIndex(OneItemIndex& rhs);
to
OneItemIndex(OneItemIndex const& rhs);
in the class definition.