there is the following code:
struct RenderableAtmosphere {
std::unique_ptr<Atmosphere> atmosphere;
float hScaleFactor, parentEarthSizeCoefficient;
bool isUseToneMapping = false;
};
struct RenderableSceneComponent {
...
std::vector<RenderableAtmosphere> atmospheres;
};
...
RenderableSceneComponent uranusSystemComponent;
uranusSystemComponent.atmospheres = vector<RenderableAtmosphere>{move(renderableUranusAtmosphere)};
//uranusSystemComponent.atmospheres.push_back(move(renderableUranusAtmosphere));
In the case of a move assignment operator call, the code does not compile with the following set of errors:
In file included from D:/MinGW/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/vector:62,
from D:\Clion\OpenGL_Projects\CourseWork_SolarSystem\src\Auxiliary_Modules/Camera.h:5,
from D:\Clion\OpenGL_Projects\CourseWork_SolarSystem\src\Auxiliary_Modules/AuxiliaryModules.h:4,
from D:\Clion\OpenGL_Projects\CourseWork_SolarSystem\src\Application.h:3,
from D:\Clion\OpenGL_Projects\CourseWork_SolarSystem\src\Application.cpp:1:
D:/MinGW/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = RenderableAtmosphere; _Args = {const RenderableAtmosphere&}]':
D:/MinGW/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_uninitialized.h:83:18: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const RenderableAtmosphere*; _ForwardIterator = RenderableAtmosphere*; bool _TrivialValueTypes = false]'
D:/MinGW/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_uninitialized.h:134:15: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const RenderableAtmosphere*; _ForwardIterator = RenderableAtmosphere*]'
D:/MinGW/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_uninitialized.h:289:37: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = const RenderableAtmosphere*; _ForwardIterator = RenderableAtmosphere*; _Tp = RenderableAtmosphere]'
D:/MinGW/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_vector.h:1464:33: required from 'void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const RenderableAtmosphere*; _Tp = RenderableAtmosphere; _Alloc = std::allocator<RenderableAtmosphere>]'
D:/MinGW/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_vector.h:519:2: required from 'std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = RenderableAtmosphere; _Alloc = std::allocator<RenderableAtmosphere>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<RenderableAtmosphere>]'
D:\Clion\OpenGL_Projects\CourseWork_SolarSystem\src\Application.cpp:888:102: required from here
D:/MinGW/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/bits/stl_construct.h:75:7: error: use of deleted function 'RenderableAtmosphere::RenderableAtmosphere(const RenderableAtmosphere&)'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
I cannot figure out at what point a copy of the class is called, which tries to call the deleted copy constructor on unique_ptr. But if you use push_back, then everything works.
The statement
uranusSystemComponent.atmospheres = vector<RenderableAtmosphere>{move(renderableUranusAtmosphere)};
calls the assignment operator of vector:
vector& operator=( const vector& other );
which requires a copy constructor for RenderableAtmosphere with the signature:
RenderableAtmosphere::RenderableAtmosphere(const RenderableAtmosphere&)
But RenderableAtmosphere does not have such a copy constructor since it has a std::unique_ptr member. Copy Constructors on cppreference.com
That's the reason why you get these error messages.
Related
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();
});
}
#include <vector>
#include <memory>
#include <iostream>
class A {
std::vector<std::unique_ptr<int>> vec;
public:
virtual ~A() = 0;
};
A::~A() {}
class B : public A {
public:
B() {}
};
int main () {
B b = B();
return 0;
}
Above is a minimal reproducible example. It does not compile, and the following error message is given:
me:~ $ g++ main2.cc
In file included from /usr/include/c++/7/vector:62:0,
from main2.cc:1:
/usr/include/c++/7/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<int>; _Args = {const std::unique_ptr<int, std::default_delete<int> >&}]’:
/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 = __gnu_cxx::__normal_iterator<const std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >; _ForwardIterator = std::unique_ptr<int>*; bool _TrivialValueTypes = false]’
/usr/include/c++/7/bits/stl_uninitialized.h:134:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >; _ForwardIterator = std::unique_ptr<int>*]’
/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 = __gnu_cxx::__normal_iterator<const std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >; _ForwardIterator = std::unique_ptr<int>*; _Tp = std::unique_ptr<int>]’
/usr/include/c++/7/bits/stl_vector.h:331:31: required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<int>; _Alloc = std::allocator<std::unique_ptr<int> >]’
main2.cc:5:7: required from here
/usr/include/c++/7/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 = int; _Dp = std::default_delete<int>]’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/memory:80:0,
from main2.cc:2:
/usr/include/c++/7/bits/unique_ptr.h:388:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^~~~~~~~~~
What it all seems like is that the copy constructor for the unique_ptr is being called somewhere.
But I have no idea why it would be called at all. When a vector is initialized, it has size 0, right? Under that assumption, no unique_ptr should be constructed.
What is the source of my compilation error?
B b = B() is a copy-initialisation and, until C++17, required that the copy be valid (even if it ended up being elided).
Even though the size of the vector in that copy is zero, that is not something that can be statically known by the innards of the copy machinery during compile-time. So, the code to make it work must be "known" during compilation, so that it is available at runtime if needed.
You probably meant just a normal declaration: B b;.
The original approach would actually have been enough if your class were trivially-moveable (because a unique_ptr can be moved), but by giving it a user-declared destructor you pessimised it. Unless you actually have a strong reason to want this class to be polymorphic, don't do that. Use = default or just omit the destructor entirely; it's not doing anything useful.
Below code compiles fine with clang but not gcc , any explanation is this a bug in gcc?
Its just a class which contains a vector of unique_ptr and std::function as member and when I create vector of this class , I cant say reserve or resize on this. push_back works fine with std::move, while this only happens with gcc and not clang.
#include <algorithm>
#include <memory>
#include <utility>
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
class ABC
{
public:
ABC()
{}
private:
std::vector<std::unique_ptr<int>> up;
std::function<void (int*)> func;
};
int main()
{
ABC a;
std::vector<ABC> vec;
vec.reserve(1);
}
Error message looks like below for gcc
In file included from /opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_tempbuf.h:60:0,
from /opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_algo.h:62,
from /opt/wandbox/gcc-7.1.0/include/c++/7.1.0/algorithm:62,
from prog.cc:1:
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<int>; _Args = {const std::unique_ptr<int, std::default_delete<int> >&}]':
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_uninitialized.h:83:18: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >; _ForwardIterator = std::unique_ptr<int>*; bool _TrivialValueTypes = false]'
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_uninitialized.h:134:15: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >; _ForwardIterator = std::unique_ptr<int>*]'
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_uninitialized.h:289:37: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >; _ForwardIterator = std::unique_ptr<int>*; _Tp = std::unique_ptr<int>]'
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_vector.h:331:31: required from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<int>; _Alloc = std::allocator<std::unique_ptr<int> >]'
prog.cc:10:7: required from 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = ABC; _Args = {const ABC&}]'
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_uninitialized.h:83:18: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const ABC*; _ForwardIterator = ABC*; bool _TrivialValueTypes = false]'
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_uninitialized.h:134:15: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const ABC*; _ForwardIterator = ABC*]'
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_uninitialized.h:289:37: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = const ABC*; _ForwardIterator = ABC*; _Tp = ABC]'
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/stl_vector.h:1263:35: 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 = const ABC*; _Tp = ABC; _Alloc = std::allocator<ABC>; std::vector<_Tp, _Alloc>::pointer = ABC*; std::vector<_Tp, _Alloc>::size_type = long unsigned int]'
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/vector.tcc:73:40: required from 'void std::vector<_Tp, _Alloc>::reserve(std::vector<_Tp, _Alloc>::size_type) [with _Tp = ABC; _Alloc = std::allocator<ABC>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]'
prog.cc:24:18: required from here
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/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 = int; _Dp = std::default_delete<int>]'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/wandbox/gcc-7.1.0/include/c++/7.1.0/memory:80:0,
from prog.cc:2:
/opt/wandbox/gcc-7.1.0/include/c++/7.1.0/bits/unique_ptr.h:388:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^~~~~~~~~~
This happens because std::function's move ctor is not noexcept, but a std::vector can only use the move ctor if it's noexcept (strong exception guarantee).
The issue is that std::unique_ptr is (obviously) non-copyable, so that makes ABC noncopyable as a whole.
To make ABC noexcept-movable implicitly, it'd need every one of its members to be noexcept-movable as well.
If you remove the std::function, that's what happens: the .resize() doesn't need to copy A.up (a std::vector's move operator is noexcept), so the std::unique_ptrs (inside up) can just be moved, and everything works fine.
See this coliru: if you comment the noexcept, vec.reserve() will need to copy everything, and the issue comes back.
Adding ABC(ABC&&) = default fixes the issue because user-declared (though defaulted) move ctor inhibits the generation of copy constructor (see here).
We can also go the opposite way and manually delete A's copy constructor in the coliru (and keep the move ctor not noexcept): here.
To fix the issue, you could store the std::function in a std::unique_ptr, which has a nothrow move ctor. See here
I think that GCC is being picky about constructors; it blocks the generation of the move-ctor1. It stops complaining after you provide them explicitely:
class ABC
{
public:
ABC() = default; // <--
ABC(ABC&&) = default; // <--
private:
std::vector<std::unique_ptr<int>> up;
std::function<void (int*)> func;
};
1 I think (again, I'm not sure), that his happens because the default copy-ctor of ABC is defined as noexcept and is as such preferred over the default move-ctor (it's still ill-formed because we're dealing with non-copyable members here). Trying to generate a defaulted noexcept move-ctor result in:
main.cpp:14:4: note: 'ABC::ABC(ABC&&) noexcept' is implicitly deleted because its exception-specification does not match the implicit exception-specification ''
ABC(ABC&&) noexcept = default;
^~~
As such, forcing the generation of no-noexcept move-ctor allows it to be picked. Why Clang doesn't have a problem with that - I don't know.
One explanation for the above is hinted by the fact that removing std::function allows the defaulted noexcept move-ctor to be generated. std::function doesn't have a noexcept move-ctor (which sucks tremendously), so the whole class falls back to the copy-ctor. Since unique_ptr doesn't have one, the whole thing breaks.
GCC accepted the lack of noexcept on std::function's move ctor as bug
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81017
// -- C++ --
/** 2227 * #brief %Function move constructor. 2228 * #param
__x A %function object rvalue with identical call signature. 2229 * 2230
* The newly-created %function contains the target of #a __x 2231 * (if
it has one). 2232 */ 2233
function(function&& __x) : _Function_base() { __x.swap(*this); }
The following example complies in clang but fails in GCC.
Original link
Code:
#include<vector>
struct Foo
{
Foo() = default;
Foo(Foo&&) = default;
};
Foo baz(std::vector<Foo> foos);
Foo bar1(Foo&& foo_)
{
std::vector<Foo> foos{std::move(foo_)};
return baz(std::move(foos));
}
Foo bar2(Foo&& foo_)
{
std::vector<Foo> foos;
foos.push_back(std::move(foo_));
return baz(std::move(foos));
}
template<typename... Foos>
Foo bar3(Foo&& foo_, Foos&&... foos_)
{
std::vector<Foo> foos{std::move(foo_), std::forward<Foos>(foos_)...};
return baz(std::move(foos));
}
void dummy()
{
Foo f1, f2;
bar3(std::move(f1), std::move(f2));
}
Errors:
In file included from /opt/gcc-4.9.0/include/c++/4.9.0/vector:62:0,
from /tmp/gcc-explorer-compiler11512-1-c5m2m1/example.cpp:1:
/opt/gcc-4.9.0/include/c++/4.9.0/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = Foo; _Args = {const Foo&}]':
/opt/gcc-4.9.0/include/c++/4.9.0/bits/stl_uninitialized.h:75:53: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const Foo*; _ForwardIterator = Foo*; bool _TrivialValueTypes = false]'
/opt/gcc-4.9.0/include/c++/4.9.0/bits/stl_uninitialized.h:125:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const Foo*; _ForwardIterator = Foo*]'
/opt/gcc-4.9.0/include/c++/4.9.0/bits/stl_uninitialized.h:278:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = const Foo*; _ForwardIterator = Foo*; _Tp = Foo]'
/opt/gcc-4.9.0/include/c++/4.9.0/bits/stl_vector.h:1286:27: required from 'void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const Foo*; _Tp = Foo; _Alloc = std::allocator<Foo>]'
/opt/gcc-4.9.0/include/c++/4.9.0/bits/stl_vector.h:378:36: required from 'std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<Foo>]'
13 : required from here
/opt/gcc-4.9.0/include/c++/4.9.0/bits/stl_construct.h:75:7: error: use of deleted function 'constexpr Foo::Foo(const Foo&)'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
3 : note: 'constexpr Foo::Foo(const Foo&)' is implicitly declared as deleted because 'Foo' declares a move constructor or move assignment operator
struct Foo
^
Compilation failed
If it is a bug in GCC, can someone suggest an easy workaround for bar3 function?
It's not possible to move out of an initializer_list, so the corresponding constructor of std::vector has to copy. That's why you're getting the errors. bar2 should compile without errors.
The normal template pack expansion trick to repeatedly call push_back should work on the variadic version.
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.