I'm trying to compile the following code (this is a minimal example), but I get a warning I can't figure out:
#include <string>
#include <variant>
#include <vector>
struct Bar {
std::wstring x = L"";
};
Bar Foo() {
std::variant<std::vector<int>, Bar> tmp = Bar();
if (std::holds_alternative<Bar>(tmp)) return std::move(std::get<Bar>(tmp));
return Bar();
}
I'm trying to build this with g++ -std=c++20 -Wall -Wextra -O2 /tmp/test.cc -c
I get the following warning:
In file included from /usr/include/x86_64-linux-gnu/c++/12/bits/c++allocator.h:33,
from /usr/include/c++/12/bits/allocator.h:46,
from /usr/include/c++/12/string:41,
from /tmp/test.cc:1:
In member function ‘void std::__new_allocator<_Tp>::deallocate(_Tp*, size_type) [with _Tp = int]’,
inlined from ‘constexpr void std::allocator< <template-parameter-1-1> >::deallocate(_Tp*, std::size_t) [with _Tp = int]’ at /usr/include/c++/12/bits/allocator.h:200:35,
inlined from ‘static constexpr void std::allocator_traits<std::allocator<_CharT> >::deallocate(allocator_type&, pointer, size_type) [with _Tp = int]’ at /usr/include/c++/12/bits/alloc_traits.h:496:23,
inlined from ‘constexpr void std::_Vector_base<_Tp, _Alloc>::_M_deallocate(pointer, std::size_t) [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:387:19,
inlined from ‘constexpr std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:366:15,
inlined from ‘constexpr std::vector<_Tp, _Alloc>::~vector() [with _Tp = int; _Alloc = std::allocator<int>]’ at /usr/include/c++/12/bits/stl_vector.h:733:7,
inlined from ‘constexpr void std::destroy_at(_Tp*) [with _Tp = vector<int>]’ at /usr/include/c++/12/bits/stl_construct.h:88:18,
inlined from ‘constexpr void std::_Destroy(_Tp*) [with _Tp = vector<int>]’ at /usr/include/c++/12/bits/stl_construct.h:149:22,
inlined from ‘std::__detail::__variant::_Variant_storage<false, std::vector<int, std::allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)> mutable [with auto:11 = std::vector<int>&]’ at /usr/include/c++/12/variant:472:19,
inlined from ‘constexpr _Res std::__invoke_impl(__invoke_other, _Fn&&, _Args&& ...) [with _Res = void; _Fn = __detail::__variant::_Variant_storage<false, vector<int, allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)>; _Args = {vector<int, allocator<int> >&}]’ at /usr/include/c++/12/bits/invoke.h:61:36,
inlined from ‘constexpr std::enable_if_t<is_invocable_r_v<_Res, _Callable, _Args ...>, _Res> std::__invoke_r(_Callable&&, _Args&& ...) [with _Res = void; _Callable = __detail::__variant::_Variant_storage<false, vector<int, allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)>; _Args = {vector<int, allocator<int> >&}]’ at /usr/include/c++/12/bits/invoke.h:111:28,
inlined from ‘static constexpr decltype(auto) std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::integer_sequence<long unsigned int, __indices ...> >::__visit_invoke(_Visitor&&, _Variants ...) [with _Result_type = void; _Visitor = std::__detail::__variant::_Variant_storage<false, std::vector<int, std::allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)>&&; _Variants = {std::variant<std::vector<int, std::allocator<int> >, Bar>&}; long unsigned int ...__indices = {0}]’ at /usr/include/c++/12/variant:1035:40,
inlined from ‘constexpr decltype(auto) std::__do_visit(_Visitor&&, _Variants&& ...) [with _Result_type = void; _Visitor = __detail::__variant::_Variant_storage<false, vector<int, allocator<int> >, Bar>::_M_reset()::<lambda(auto:11&&)>; _Variants = {variant<vector<int, allocator<int> >, Bar>&}]’ at /usr/include/c++/12/variant:1783:5,
inlined from ‘constexpr void std::__detail::__variant::_Variant_storage<false, _Types ...>::_M_reset() [with _Types = {std::vector<int, std::allocator<int> >, Bar}]’ at /usr/include/c++/12/variant:470:23,
inlined from ‘constexpr std::__detail::__variant::_Variant_storage<false, _Types ...>::~_Variant_storage() [with _Types = {std::vector<int, std::allocator<int> >, Bar}]’ at /usr/include/c++/12/variant:480:17,
inlined from ‘constexpr std::__detail::__variant::_Copy_ctor_base<false, std::vector<int, std::allocator<int> >, Bar>::~_Copy_ctor_base()’ at /usr/include/c++/12/variant:554:12,
inlined from ‘constexpr std::__detail::__variant::_Move_ctor_base<false, std::vector<int, std::allocator<int> >, Bar>::~_Move_ctor_base()’ at /usr/include/c++/12/variant:591:12,
inlined from ‘constexpr std::__detail::__variant::_Copy_assign_base<false, std::vector<int, std::allocator<int> >, Bar>::~_Copy_assign_base()’ at /usr/include/c++/12/variant:629:12,
inlined from ‘constexpr std::__detail::__variant::_Move_assign_base<false, std::vector<int, std::allocator<int> >, Bar>::~_Move_assign_base()’ at /usr/include/c++/12/variant:681:12,
inlined from ‘constexpr std::__detail::__variant::_Variant_base<std::vector<int, std::allocator<int> >, Bar>::~_Variant_base()’ at /usr/include/c++/12/variant:735:12,
inlined from ‘constexpr std::variant<_Types>::~variant() [with _Types = {std::vector<int, std::allocator<int> >, Bar}]’ at /usr/include/c++/12/variant:1407:28,
inlined from ‘Bar Foo()’ at /tmp/test.cc:13:1:
/usr/include/c++/12/bits/new_allocator.h:158:33: warning: ‘void operator delete(void*, std::size_t)’ called on unallocated object ‘tmp’ [-Wfree-nonheap-object]
158 | _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
| ^
/tmp/test.cc: In function ‘Bar Foo()’:
/tmp/test.cc:10:39: note: declared here
10 | std::variant<std::vector<int>, Bar> tmp = Bar();
| ^~~
g++ --version says g++ (Debian 12.2.0-10) 12.2.0
I know this code, as is, doesn't make that much sense; but it also shouldn't have this problem: this is a minimal example that exhibits this warning, of a much more complex function.
Strangely, the warning disappears if I do any of the following:
Change Bar::x to be a std::string.
Change tmp to be std::variant<int, Bar> (rather than having a std::vector<int> as the first type).
Remove g++ command-line flag -O2 (i.e., compile with g++ -std=c++20 -Wall -Wextra -O2 /tmp/test.cc -c).
Why would any of these changes make the warning go away!?
If I build this with --std=c++17, the problem remains.
The -Wfree-nonheap-object flag of gcc has a series of false positives bugs, among which bug 99098 is used to record these meta-bugs.
The bug in your example is similar to bug 108088 and has been listed, which issues a false positive warning message since gcc-12.
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
The following piece of code compiles fine in g++ 8.3 and 7.4 when -std=c++17 is set:
#include <any>
#include <tuple>
#include <vector>
int main()
{
std::vector<std::tuple<std::any>> f2;
f2.emplace_back(42);
return 0;
}
VS2017 works well, too.
But with g++ 9.1 I see this error:
In file included from /usr/include/c++/9/bits/move.h:55,
from /usr/include/c++/9/bits/nested_exception.h:40,
from /usr/include/c++/9/exception:144,
from /usr/include/c++/9/new:40,
from /usr/include/c++/9/any:37,
from a.cpp:1:
/usr/include/c++/9/type_traits: In instantiation of ‘struct std::__and_<std::is_constructible<std::tuple<std::any>, std::tuple<std::any>&&>, std::__is_nt_constructible_impl<std::tuple<std::any>, std::tuple<std::any>&&> >’:
/usr/include/c++/9/type_traits:974:12: required from ‘struct std::is_nothrow_constructible<std::tuple<std::any>, std::tuple<std::any>&&>’
/usr/include/c++/9/type_traits:1005:12: required from ‘struct std::__is_nothrow_move_constructible_impl<std::tuple<std::any>, true>’
/usr/include/c++/9/type_traits:1011:12: required from ‘struct std::is_nothrow_move_constructible<std::tuple<std::any> >’
/usr/include/c++/9/any:95:67: required by substitution of ‘template<class _Tp, class _Safe, bool _Fits> using _Internal = std::integral_constant<bool, (_Safe::value && _Fits)> [with _Tp = std::tuple<std::any>; _Safe = std::is_nothrow_move_constructible<std::tuple<std::any> >; bool _Fits = ((sizeof (std::tuple<std::any>) <= sizeof (std::any::_Storage)) && (8 <= 8))]’
/usr/include/c++/9/any:104:13: required by substitution of ‘template<class _Tp> using _Manager = std::conditional_t<std::any::_Internal<_Tp>::value, std::any::_Manager_internal<_Tp>, std::any::_Manager_external<_Tp> > [with _Tp = std::tuple<std::any>]’
/usr/include/c++/9/any:180:8: [ skipping 3 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/9/type_traits:925:12: required from ‘struct std::is_move_constructible<std::tuple<std::any> >’
/usr/include/c++/9/bits/alloc_traits.h:619:12: required from ‘struct std::__is_move_insertable<std::allocator<std::tuple<std::any> > >’
/usr/include/c++/9/bits/stl_vector.h:446:28: required from ‘static constexpr bool std::vector<_Tp, _Alloc>::_S_use_relocate() [with _Tp = std::tuple<std::any>; _Alloc = std::allocator<std::tuple<std::any> >]’
/usr/include/c++/9/bits/vector.tcc:459:44: required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {int}; _Tp = std::tuple<std::any>; _Alloc = std::allocator<std::tuple<std::any> >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<std::tuple<std::any>*, std::vector<std::tuple<std::any> > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = std::tuple<std::any>*]’
/usr/include/c++/9/bits/vector.tcc:121:4: required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {int}; _Tp = std::tuple<std::any>; _Alloc = std::allocator<std::tuple<std::any> >; std::vector<_Tp, _Alloc>::reference = std::tuple<std::any>&]’
a.cpp:8:21: required from here
/usr/include/c++/9/type_traits:131:12: error: incomplete type ‘std::is_constructible<std::tuple<std::any>, std::tuple<std::any>&&>’ used in nested name specifier
131 | struct __and_<_B1, _B2>
| ^~~~~~~~~~~~~~~~
Is there something wrong with the code or is it a g++-9 issue?
It is a gcc problem, which was fixed after version 9.5 (Bug report). We can reproduce this problem in all 9.1 - 9.4 versions. Also, we can produce success build in 8.X versions.
Compared versions 8.5 (OK), 9.1 (NOK) and 10.1 (OK) in compiler explorer. All is flaged with -std=c++17 without any other optimizations.
I have a class, which looks like that:
template<typename T>
using VectorPtr=std::vector<std::unique_ptr<T>>;
template<typename T>
using VectorRawPtr=std::vector<T*>;
class ItemsSet{ // <-- Compiler say this line contans an error 0_o ?
public:
ItemsSet(VectorPtr<Item>& items);
~ItemsSet() = default;
VectorRawPtr<Item> GetItems();
VectorRawPtr<Item> GetSuitableItemsForPeriod(const IPeriod &period);
double CalculateTotal();
private:
VectorPtr<Item> _items;
};
constructor looks like:
ItemsSet::ItemsSet(VectorPtr<Item> & items) {
for(auto &itm: items){
_items.emplace_back(std::move(itm));
}
}
however this code isn't compiled and failed with error:
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<Item, std::default_delete<Item> >; _Args = {const std::unique_ptr<Item, std::default_delete<Item> >&}]':
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_uninitialized.h:75:18: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<Item, std::default_delete<Item> >*, std::vector<std::unique_ptr<Item, std::default_delete<Item> >, std::allocator<std::unique_ptr<Item, std::default_delete<Item> > > > >; _ForwardIterator = std::unique_ptr<Item, std::default_delete<Item> >*; bool _TrivialValueTypes = false]'
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_uninitialized.h:126:15: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<Item, std::default_delete<Item> >*, std::vector<std::unique_ptr<Item, std::default_delete<Item> >, std::allocator<std::unique_ptr<Item, std::default_delete<Item> > > > >; _ForwardIterator = std::unique_ptr<Item, std::default_delete<Item> >*]'
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_uninitialized.h:281:37: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<Item, std::default_delete<Item> >*, std::vector<std::unique_ptr<Item, std::default_delete<Item> >, std::allocator<std::unique_ptr<Item, std::default_delete<Item> > > > >; _ForwardIterator = std::unique_ptr<Item, std::default_delete<Item> >*; _Tp = std::unique_ptr<Item, std::default_delete<Item> >]'
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_vector.h:322:31: required from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<Item, std::default_delete<Item> >; _Alloc = std::allocator<std::unique_ptr<Item, std::default_delete<Item> > >]'
/cygdrive/d/code/itemSet.h:4:19: required from here
/usr/lib/gcc/x86_64-pc-cygwin/5.4.0/include/c++/bits/stl_construct.h:75:7: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Item; _Dp = std::default_delete<Item>]'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
Could anyone explain me what I'm doing wrong and how could I fix my problem?
I'm pretty sure that actual problem is an implicit copy constructor ither for ItemsSet or Item. Because you using unique_ptr's which can't really be copied, copy constructor can't be generated properly. Try to explicitly delete copy constructors and find the place where they used and change those place to move declaration for example, or use shared pointers.
This isn't the actual code that produces the error (your line numbers don't match, and neither do the errors; you should present an actual testcase here), but we can still see the problem.
unique_ptrs cannot be copied (they're "unique"!), yet by copy-initialising _items from a whole vector of them, you're attempting to copy them all. You can't do that.
You could move the constructor argument into _items instead.
I don't know if this will fix it or not, but you might try moving the constructor parameter directly into _items instead of moving each individual member into it:
ItemsSet::ItemsSet(VectorPtr<Item>&& items)
: _items(std::move(items))
{
}
How can I use boost::assign::list_of to put values into an object of type std::vector<std::vector<int> >? Or have you any other suggestions as to how I can populate it for the purposes of unit testing?
UPDATED
I get the following compiler error for gcc 4.4.2
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_uninitialized.h: In static member function 'static _ForwardIterator std::__uninitialized_copy<<anonymous> >::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::_Deque_iterator<boost::assign_detail::generic_list<int>, boost::assign_detail::generic_list<int>&, boost::assign_detail::generic_list<int>*>, _ForwardIterator = std::vector<int, std::allocator<int> >*, bool <anonymous> = false]':
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_uninitialized.h:117: instantiated from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::_Deque_iterator<boost::assign_detail::generic_list<int>, boost::assign_detail::generic_list<int>&, boost::assign_detail::generic_list<int>*>, _ForwardIterator = std::vector<int, std::allocator<int> >*]'
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_uninitialized.h:257: instantiated from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::_Deque_iterator<boost::assign_detail::generic_list<int>, boost::assign_detail::generic_list<int>&, boost::assign_detail::generic_list<int>*>, _ForwardIterator = std::vector<int, std::allocator<int> >*, _Tp = std::vector<int, std::allocator<int> >]'
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_vector.h:1024: instantiated from 'void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = std::_Deque_iterator<boost::assign_detail::generic_list<int>, boost::assign_detail::generic_list<int>&, boost::assign_detail::generic_list<int>*>, _Tp = std::vector<int, std::allocator<int> >, _Alloc = std::allocator<std::vector<int, std::allocator<int> > >]'
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_vector.h:1002: instantiated from 'void std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = std::_Deque_iterator<boost::assign_detail::generic_list<int>, boost::assign_detail::generic_list<int>&, boost::assign_detail::generic_list<int>*>, _Tp = std::vector<int, std::allocator<int> >, _Alloc = std::allocator<std::vector<int, std::allocator<int> > >]'
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_vector.h:303: instantiated from 'std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const _Alloc&) [with _InputIterator = std::_Deque_iterator<boost::assign_detail::generic_list<int>, boost::assign_detail::generic_list<int>&, boost::assign_detail::generic_list<int>*>, _Tp = std::vector<int, std::allocator<int> >, _Alloc = std::allocator<std::vector<int, std::allocator<int> > >]'
/boost/boost_1_51_0/boost/assign/list_of.hpp:163: instantiated from 'Container boost::assign_detail::converter<DerivedTAssign, Iterator>::convert(const Container*, boost::assign_detail::default_type_tag) const [with Container = std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >, DerivedTAssign = boost::assign_detail::generic_list<boost::assign_detail::generic_list<int> >, Iterator = std::_Deque_iterator<boost::assign_detail::generic_list<int>, boost::assign_detail::generic_list<int>&, boost::assign_detail::generic_list<int>*>]'
/boost/boost_1_51_0/boost/assign/list_of.hpp:142: instantiated from 'Container boost::assign_detail::converter<DerivedTAssign, Iterator>::convert_to_container() const [with Container = std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >, DerivedTAssign = boost::assign_detail::generic_list<boost::assign_detail::generic_list<int> >, Iterator = std::_Deque_iterator<boost::assign_detail::generic_list<int>, boost::assign_detail::generic_list<int>&, boost::assign_detail::generic_list<int>*>]'
/boost/boost_1_51_0/boost/assign/list_of.hpp:436: instantiated from 'boost::assign_detail::generic_list<T>::operator Container() const [with Container = std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >, T = boost::assign_detail::generic_list<int>]'
main.cc:1: instantiated from here
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_uninitialized.h:74: error: call of overloaded 'vector(boost::assign_detail::generic_list<int>&)' is ambiguous
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_vector.h:241: note: candidates are: std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = int, _Alloc = std::allocator<int>]
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_vector.h:227: note: std::vector<_Tp, _Alloc>::vector(size_t, const _Tp&, const _Alloc&) [with _Tp = int, _Alloc = std::allocator<int>]
gcc/4.4.2/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/bits/stl_vector.h:215: note: std::vector<_Tp, _Alloc>::vector(const _Alloc&) [with _Tp = int, _Alloc = std::allocator<int>]
Here's my code:
std::vector< std::vector<int> > v = boost::assign::list_of
( boost::assign::list_of(1)(2) )
( boost::assign::list_of(3) )
( boost::assign::list_of(5)(6)(7)(8) );
#include <boost/range/algorithm.hpp>
#include <boost/foreach.hpp>
#include <boost/assign.hpp>
#include <iterator>
#include <iostream>
#include <ostream>
#include <vector>
int main()
{
using namespace boost;
using namespace assign;
using namespace std;
vector< vector<int> > v = list_of
( list_of(1)(2) )
( list_of(3) )
( list_of(5)(6)(7)(8) );
BOOST_FOREACH(const vector<int> &x, v)
{
copy(x,ostream_iterator<int>(cout," "));
cout << endl;
}
}
Output is:
1 2
3
5 6 7 8
I get the following compiler error for gcc 4.4.2
Follwing code works on GCC 4.4.6:
vector< vector<int> > v;
v += list_of(1)(2),
list_of(3),
list_of(5)(6)(7)(8);
#include <functional>
#include <algorithm>
#include <list>
using namespace std;
struct foo{
int _val;
};
int main(){
list<foo> A;
foo B;
for(int i=0;i<10;++i){
B._val=i;
A.push_back(B);
}
list< reference_wrapper < foo > > C(A.begin(),A.end());
return 0;
}
I am trying to use std::reference_wrapper to hold references to type "foo" but when I do this I get a very peculiar compiler error:
>In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/list:63,
from ref_wrapper.cpp:4:/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h: In member function \u2018void std::list<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = std::_List_iterator<foo>, _Tp = std::reference_wrapper<foo>, _Alloc = std::allocator<std::reference_wrapper<foo> >]\u2019:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h:577: instantiated from \u2018std::list<_Tp, _Alloc>::list(_InputIterator, _InputIterator, const _Alloc&) [with _InputIterator = std::_List_iterator<foo>, _Tp = std::reference_wrapper<foo>, _Alloc = std::allocator<std::reference_wrapper<foo> >]\u2019
ref_wrapper.cpp:19: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h:1361: error: no matching function for call to \u2018std::list<std::reference_wrapper<foo>, std::allocator<std::reference_wrapper<foo> > >::push_back(foo&)\u2019
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h:919: note: candidates are: void std::list<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = std::reference_wrapper<foo>, _Alloc = std::allocator<std::reference_wrapper<foo> >]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_list.h:924: note: void std::list<_Tp, _Alloc>::push_back(_Tp&&) [with _Tp = std::reference_wrapper<foo>, _Alloc = std::allocator<std::reference_wrapper<foo> >]
It is impossible to discern what is going on. I have tried the same code on VS 2010 and it worked. I am wondering why it's not working for g++
The command I entered in terminal was:
g++ -std=gnu++0x reference_wrapper_test.cpp -o reference_wrapper_test
I think that you could update your compiler .
See the Link : http://liveworkspace.org/code/3mVcGp$6