Consider the following C++11 code:
#include <thread>
#include <vector>
struct A {
A() {}
//virtual ~A() = default;
//~A() = default;
//~A() {};
std::thread t;
};
int main()
{
std::vector<A> v;
v.emplace_back();
}
If any of the lines declaring the destructor on the previous code is uncommented, this code won't compile. The compiler complains about copy construtor of std::thread being deleted. But std::vector::emplace_back should make no use of copy constructor, so, why it fails? And why the heck the mention of the destructor matters?
GCC output (~A() {}; uncommented):
$ g++ --std=c++11 -o test test.cpp
In file included from /usr/include/c++/4.8/memory:64:0,
from /usr/include/c++/4.8/thread:40,
from test.cpp:1:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = A; _Args = {A}]’:
/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<A*>; _ForwardIterator = A*; 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<A*>; _ForwardIterator = A*]’
/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<A*>; _ForwardIterator = A*; _Tp = A]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:281:69: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = A*; _ForwardIterator = A*; _Allocator = std::allocator<A>]’
/usr/include/c++/4.8/bits/vector.tcc:415:43: required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {}; _Tp = A; _Alloc = std::allocator<A>]’
/usr/include/c++/4.8/bits/vector.tcc:101:54: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {}; _Tp = A; _Alloc = std::allocator<A>]’
test.cpp:17:17: required from here
/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘A::A(const A&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
test.cpp:4:8: note: ‘A::A(const A&)’ is implicitly deleted because the default definition would be ill-formed:
struct A {
^
test.cpp:4:8: error: use of deleted function ‘std::thread::thread(const std::thread&)’
In file included from test.cpp:1:0:
/usr/include/c++/4.8/thread:126:5: error: declared here
thread(const thread&) = delete;
^
Clang output (~A() {}; uncommented):
$ clang++ --std=c++11 -o test test.cpp
In file included from test.cpp:1:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:40:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/memory:64:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_construct.h:75:38: error:
call to implicitly-deleted copy constructor of 'A'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:75:8: note:
in instantiation of function template specialization
'std::_Construct<A, A>' requested here
std::_Construct(std::__addressof(*__cur), *__first);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:117:2: note:
in instantiation of function template specialization
'std::__uninitialized_copy<false>::__uninit_copy<std::move_iterator<A *>,
A *>' requested here
__uninit_copy(__first, __last, __result);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:258:19: note:
in instantiation of function template specialization
'std::uninitialized_copy<std::move_iterator<A *>, A *>' requested here
{ return std::uninitialized_copy(__first, __last, __result); }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:279:19: note:
in instantiation of function template specialization
'std::__uninitialized_copy_a<std::move_iterator<A *>, A *, A>' requested
here
return std::__uninitialized_copy_a
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/vector.tcc:413:15: note:
in instantiation of function template specialization
'std::__uninitialized_move_if_noexcept_a<A *, A *, std::allocator<A> >'
requested here
= std::__uninitialized_move_if_noexcept_a
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/vector.tcc:101:4: note:
in instantiation of function template specialization 'std::vector<A,
std::allocator<A> >::_M_emplace_back_aux<>' requested here
_M_emplace_back_aux(std::forward<_Args>(__args)...);
^
test.cpp:17:4: note: in instantiation of function template specialization
'std::vector<A, std::allocator<A> >::emplace_back<>' requested here
v.emplace_back();
^
test.cpp:11:14: note: copy constructor of 'A' is implicitly deleted because
field 't' has a deleted copy constructor
std::thread t;
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:126:5: note:
'thread' has been explicitly marked deleted here
thread(const thread&) = delete;
^
1 error generated.
(Answer taken from comments, no credit taken by me)
If a destructor is declared manually, the default move constructor is not created when compiling. Forcing the default move constructor to be used will fix this:
A(A&& o) = default;
Related
I am new to object oriented programming. I am trying to make a game called Hex. I use a static vector of Hex objects to hold active games (there can be more then one active game). But whenever I try to pushback a new game to Hex vector, I get this weird error:
In file included from /usr/include/i386-linux-gnu/c++/4.8/bits/c++allocator.h:33:0,
from /usr/include/c++/4.8/bits/allocator.h:46,
from /usr/include/c++/4.8/string:41,
from /usr/include/c++/4.8/bits/locale_classes.h:40,
from /usr/include/c++/4.8/bits/ios_base.h:41,
from /usr/include/c++/4.8/ios:42,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from HEX.cpp:1:
/usr/include/c++/4.8/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Hex; _Args = {const Hex&}; _Tp = Hex]’:
/usr/include/c++/4.8/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 = Hex; _Args = {const Hex&}; _Alloc = std::allocator<Hex>; typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type = void]’
/usr/include/c++/4.8/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 = Hex; _Args = {const Hex&}; _Alloc = std::allocator<Hex>; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]’
/usr/include/c++/4.8/bits/stl_vector.h:906:34: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Hex; _Alloc = std::allocator<Hex>; std::vector<_Tp, _Alloc>::value_type = Hex]’
HEX.cpp:50:22: required from here
/usr/include/c++/4.8/ext/new_allocator.h:120:4: error: use of deleted function ‘Hex::Hex(const Hex&)’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
HEX.cpp:7:7: note: ‘Hex::Hex(const Hex&)’ is implicitly deleted because the default definition would be ill-formed:
class Hex{
^
HEX.cpp:7:7: error: use of deleted function ‘std::basic_ofstream<char>::basic_ofstream(const std::basic_ofstream<char>&)’
In file included from HEX.cpp:3:0:
/usr/include/c++/4.8/fstream:599:11: note: ‘std::basic_ofstream<char>::basic_ofstream(const std::basic_ofstream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
class basic_ofstream : public basic_ostream<_CharT,_Traits>
^
/usr/include/c++/4.8/fstream:599:11: error: use of deleted function ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’
In file included from /usr/include/c++/4.8/iostream:39:0,
from HEX.cpp:1:
/usr/include/c++/4.8/ostream:58:11: note: ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
class basic_ostream : virtual public basic_ios<_CharT, _Traits>
^
/usr/include/c++/4.8/ostream:58:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
In file included from /usr/include/c++/4.8/ios:44:0,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from HEX.cpp:1:
/usr/include/c++/4.8/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
^
In file included from /usr/include/c++/4.8/ios:42:0,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from HEX.cpp:1:
/usr/include/c++/4.8/bits/ios_base.h:792:5: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
ios_base(const ios_base&);
^
In file included from /usr/include/c++/4.8/ios:44:0,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from HEX.cpp:1:
/usr/include/c++/4.8/bits/basic_ios.h:66:11: error: within this context
class basic_ios : public ios_base
^
In file included from HEX.cpp:3:0:
/usr/include/c++/4.8/fstream:599:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
class basic_ofstream : public basic_ostream<_CharT,_Traits>
^
/usr/include/c++/4.8/fstream:599:11: error: use of deleted function ‘std::basic_filebuf<char>::basic_filebuf(const std::basic_filebuf<char>&)’
/usr/include/c++/4.8/fstream:72:11: note: ‘std::basic_filebuf<char>::basic_filebuf(const std::basic_filebuf<char>&)’ is implicitly deleted because the default definition would be ill-formed:
class basic_filebuf : public basic_streambuf<_CharT, _Traits>
^
In file included from /usr/include/c++/4.8/ios:43:0,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from HEX.cpp:1:
/usr/include/c++/4.8/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)
^
In file included from HEX.cpp:3:0:
/usr/include/c++/4.8/fstream:72:11: error: within this context
class basic_filebuf : public basic_streambuf<_CharT, _Traits>
^
In file included from /usr/include/c++/4.8/vector:62:0,
from HEX.cpp:2:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = Hex; _Args = {Hex}]’:
/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<Hex*>; _ForwardIterator = Hex*; 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<Hex*>; _ForwardIterator = Hex*]’
/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<Hex*>; _ForwardIterator = Hex*; _Tp = Hex]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:281:69: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Hex*; _ForwardIterator = Hex*; _Allocator = std::allocator<Hex>]’
/usr/include/c++/4.8/bits/vector.tcc:415:43: required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {const Hex&}; _Tp = Hex; _Alloc = std::allocator<Hex>]’
/usr/include/c++/4.8/bits/stl_vector.h:911:27: required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = Hex; _Alloc = std::allocator<Hex>; std::vector<_Tp, _Alloc>::value_type = Hex]’
HEX.cpp:50:22: required from here
/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘Hex::Hex(Hex&&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
HEX.cpp:7:7: note: ‘Hex::Hex(Hex&&)’ is implicitly deleted because the default definition would be ill-formed:
class Hex{
^
HEX.cpp:7:7: error: use of deleted function ‘std::basic_ofstream<char>::basic_ofstream(const std::basic_ofstream<char>&)’
And here is my code(problem is in the addNewGame() function right after the class. When I delete games.push_back(game), there is no error.):
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
class Hex{
public:
Hex() : Hex(6){/*Intentionally empty*/};
Hex(int x); //boardSize
inline void setBoardSize(int x){if(x>5) boardSize = x;}
inline int getBoardSize(){return boardSize;}
void printBoardSize();
void saveGame(const string& fileName);
void loadGame(const string& fileName);
void printBoard();
void playGame();
void play();
void play(string cellPos,int player); //if player is 1 puts 'x', if it is 2 puts 'o'
inline void setGameMode(int x){if(x ==1 || x==2) gameMode = x;}
inline int getGameMode(){return gameMode;}
static void addNewGame();
static vector <Hex> games; //holds the active hex games.
private:
int boardSize;
int gameMode; //if 1 PVP, else if 2 PVCOMP
ofstream saveFile;
class Cell{
public:
Cell();
Cell(int x,int y);
enum cellState{empty = '.',p1='x',p2='o',p1won='X',p2won='O'};
void setColumn(int x,Hex game);
inline int getColumn(){return column;}
void setRow(int x,Hex game);
inline int getRow(){return row;}
inline void setState(cellState x){state=x;}
inline int getState(){return state;}
private:
int column;
int row;
cellState state;
};
vector< vector<Cell> > hexCells;
};
vector <Hex> Hex::games;
void Hex::addNewGame(){
Hex game;
games.push_back(game);
}
Pushing back to vector contains copying ob object. Copying of std::ofstream is prohivited.
It seesm the variable ofstream saveFile; is used only in the function Hex::saveGame, so you should declare the variable as local variable like ifstream loadFile; in the function Hex::loadGame instead of as member variable.
Your hex class has a member saveFile of type std::ofstream. Since a std::ofstream has a deleted copy constructor, Hex becomes non copy-constructible either, which is why push_back doesn't work to add a Hex object.
You could fix this by making saveFile a reference member, i.e. a std::ofstream&, which would make Hex copy-constructible again. However, you would need to initialize this member in a member-initializer-list. But since you don't know the name of the file when constructing a Hex object that approach won't work.
Since saveFile only appears to be used in saveGame, a simple fix would be to just declare it as a local variable in that function:
void Hex::saveGame(const string& fileName){
ofstream saveFile;
saveFile.open(fileName);
// ...
}
Here's a demo.
#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.
Is it possible to build a vector of mocked objects in Google Test/Mock? I have a scenario, where I want to return a vector of custom objects (Foo) from an object (Bar). So I was trying return vector with mocked version of that class (std::vector<Foo>).
Example code:
class Foo {
public:
virtual int op(int a , int b) {
return 0;
}
};
class Bar {
public:
virtual std::vector<Foo> getFoos() {
std::vector<Foo> v;
// ...
// Some logic to fill this vector
// ...
return v;
}
};
class MockFoo : public Foo {
public:
MOCK_METHOD2(op, int(int, int));
};
class MockBar : public Bar {
public:
MOCK_METHOD0(getFoos, std::vector<Foo>());
};
TEST(Foo, test_op) {
vector<MockFoo> v;
v.emplace_back();
ASSERT_EQ(v.size(), 1);
MockBar bar;
EXPECT_CALL(bar, getFoos())
.WillRepeatedly(Return(v));
}
I am getting
In file included from .../googlemock/include/gmock/gmock.h:58:0,
from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-actions.h: In instantiation of ‘testing::internal::ReturnAction<R>::Impl<R_, F>::Impl(const testing::internal::linked_ptr<T>&) [with R_ = std::vector<MockFoo>; F = std::vector<Foo>(); R = std::vector<MockFoo>]’:
.../googlemock/include/gmock/gmock-actions.h:557:44: required from ‘testing::internal::ReturnAction<R>::operator testing::Action<Func>() const [with F = std::vector<Foo>(); R = std::vector<MockFoo>]’
.../FooBarTest.cpp:65:38: required from here
.../googlemock/include/gmock/gmock-actions.h:577:39: error: no matching function for call to ‘ImplicitCast_(std::vector<MockFoo>&)’
value_(ImplicitCast_<Result>(value_before_cast_)) {}
^
In file included from .../googletest/include/gtest/internal/gtest-internal.h:40:0,
from .../googletest/include/gtest/gtest.h:58,
from .../FooBarTest.cpp:1:
.../googletest/include/gtest/internal/gtest-port.h:1343:11: note: candidate: template<class To> To testing::internal::ImplicitCast_(To)
inline To ImplicitCast_(To x) { return x; }
^
.../googletest/include/gtest/internal/gtest-port.h:1343:11: note: template argument deduction/substitution failed:
In file included from .../googlemock/include/gmock/gmock.h:58:0,
from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-actions.h:577:39: note: cannot convert ‘((testing::internal::ReturnAction<std::vector<MockFoo> >::Impl<std::vector<MockFoo>, std::vector<Foo>()>*)this)->testing::internal::ReturnAction<std::vector<MockFoo> >::Impl<std::vector<MockFoo>, std::vector<Foo>()>::value_before_cast_’ (type ‘std::vector<MockFoo>’) to type ‘std::vector<Foo>’
value_(ImplicitCast_<Result>(value_before_cast_)) {}
^
In file included from /usr/include/c++/5/vector:62:0,
from .../googletest/include/gtest/gtest.h:56,
from .../FooBarTest.cpp:1:
/usr/include/c++/5/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = MockFoo; _Args = {const MockFoo&}]’:
/usr/include/c++/5/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 MockFoo*, std::vector<MockFoo> >; _ForwardIterator = MockFoo*; bool _TrivialValueTypes = false]’
/usr/include/c++/5/bits/stl_uninitialized.h:126:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const MockFoo*, std::vector<MockFoo> >; _ForwardIterator = MockFoo*]’
/usr/include/c++/5/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 MockFoo*, std::vector<MockFoo> >; _ForwardIterator = MockFoo*; _Tp = MockFoo]’
/usr/include/c++/5/bits/stl_vector.h:322:31: required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = MockFoo; _Alloc = std::allocator<MockFoo>]’
.../FooBarTest.cpp:65:37: required from here
/usr/include/c++/5/bits/stl_construct.h:75:7: error: use of deleted function ‘MockFoo::MockFoo(const MockFoo&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
.../FooBarTest.cpp:40:7: note: ‘MockFoo::MockFoo(const MockFoo&)’ is implicitly deleted because the default definition would be ill-formed:
class MockFoo : public Foo {
^
.../FooBarTest.cpp:40:7: error: use of deleted function ‘testing::internal::FunctionMocker<int(int, int)>::FunctionMocker(const testing::internal::FunctionMocker<int(int, int)>&)’
In file included from .../googlemock/include/gmock/gmock.h:61:0,
from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-generated-function-mockers.h:106:7: note: ‘testing::internal::FunctionMocker<int(int, int)>::FunctionMocker(const testing::internal::FunctionMocker<int(int, int)>&)’ is implicitly deleted because the default definition would be ill-formed:
class FunctionMocker<R(A1, A2)> : public
^
In file included from .../googletest/include/gtest/internal/gtest-internal.h:40:0,
from .../googletest/include/gtest/gtest.h:58,
from .../FooBarTest.cpp:1:
.../googlemock/include/gmock/gmock-spec-builders.h:1784:35: error: ‘testing::internal::FunctionMockerBase<F>::FunctionMockerBase(const testing::internal::FunctionMockerBase<F>&) [with F = int(int, int)]’ is private
GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase);
^
.../googletest/include/gtest/internal/gtest-port.h:875:3: note: in definition of macro ‘GTEST_DISALLOW_COPY_AND_ASSIGN_’
type(type const &);\
^
In file included from .../googlemock/include/gmock/gmock.h:61:0,
from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-generated-function-mockers.h:106:7: error: within this context
class FunctionMocker<R(A1, A2)> : public
^
In file included from /usr/include/c++/5/vector:62:0,
from .../googletest/include/gtest/gtest.h:56,
from .../FooBarTest.cpp:1:
/usr/include/c++/5/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = MockFoo; _Args = {MockFoo}]’:
/usr/include/c++/5/bits/stl_uninitialized.h:75:18: required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<MockFoo*>; _ForwardIterator = MockFoo*; bool _TrivialValueTypes = false]’
/usr/include/c++/5/bits/stl_uninitialized.h:126:15: required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<MockFoo*>; _ForwardIterator = MockFoo*]’
/usr/include/c++/5/bits/stl_uninitialized.h:281:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<MockFoo*>; _ForwardIterator = MockFoo*; _Tp = MockFoo]’
/usr/include/c++/5/bits/stl_uninitialized.h:303:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = MockFoo*; _ForwardIterator = MockFoo*; _Allocator = std::allocator<MockFoo>]’
/usr/include/c++/5/bits/vector.tcc:422:8: required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {}; _Tp = MockFoo; _Alloc = std::allocator<MockFoo>]’
/usr/include/c++/5/bits/vector.tcc:101:23: required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {}; _Tp = MockFoo; _Alloc = std::allocator<MockFoo>]’
.../FooBarTest.cpp:56:20: required from here
/usr/include/c++/5/bits/stl_construct.h:75:7: error: use of deleted function ‘MockFoo::MockFoo(MockFoo&&)’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
.../FooBarTest.cpp:40:7: note: ‘MockFoo::MockFoo(MockFoo&&)’ is implicitly deleted because the default definition would be ill-formed:
class MockFoo : public Foo {
^
.../FooBarTest.cpp:40:7: error: use of deleted function ‘testing::internal::FunctionMocker<int(int, int)>::FunctionMocker(testing::internal::FunctionMocker<int(int, int)>&&)’
In file included from .../googlemock/include/gmock/gmock.h:61:0,
from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-generated-function-mockers.h:106:7: note: ‘testing::internal::FunctionMocker<int(int, int)>::FunctionMocker(testing::internal::FunctionMocker<int(int, int)>&&)’ is implicitly deleted because the default definition would be ill-formed:
class FunctionMocker<R(A1, A2)> : public
^
In file included from .../googletest/include/gtest/internal/gtest-internal.h:40:0,
from .../googletest/include/gtest/gtest.h:58,
from .../FooBarTest.cpp:1:
.../googlemock/include/gmock/gmock-spec-builders.h:1784:35: error: ‘testing::internal::FunctionMockerBase<F>::FunctionMockerBase(const testing::internal::FunctionMockerBase<F>&) [with F = int(int, int)]’ is private
GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase);
^
.../googletest/include/gtest/internal/gtest-port.h:875:3: note: in definition of macro ‘GTEST_DISALLOW_COPY_AND_ASSIGN_’
type(type const &);\
^
In file included from .../googlemock/include/gmock/gmock.h:61:0,
from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-generated-function-mockers.h:106:7: error: within this context
class FunctionMocker<R(A1, A2)> : public
To my best understanding it is due to the fact Google test mock classes are not copyable. I explicitly don't need a copyable mock class. I just need the ability to return list of mocked object. Is it possible in Google test (release-1.8.0)?
One alternative that comes to mind is implement an iterator like patter in Bar, so that it behaves like a vector. However, I want to avoid that approach if possible.
You need to implement a copy constructor inside your Mockclass, that's how I managed to create a mock class vector. Probably something like this:
MockClass(const MockClass& other) {
setDefaultBehaviors();
defaultId = other.defaultId;
}
I'm seeing some errors passing std::vector< std::unique_ptr< T > > around with std::move. The code that reproduces the problem is this:
#include <memory> // for std::unique_ptr
#include <utility> // for std::move
#include <vector> // for std::vector
struct bar {};
using vtype = std::vector<std::unique_ptr<bar>>;
struct foo
{
foo(vtype v) : _v(std::move(v)) { }
private:
vtype _v;
};
vtype getVector()
{
return { std::move( std::unique_ptr<bar>(new bar()) ) };
};
int main()
{
foo f(std::move(getVector()));
};
With clang 3.4, this code produces this error:
$ clang++ -std=c++11 test.cpp -o xtest
In file included from test.cpp:1:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/memory:64:
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_construct.h:75:38: error: call to deleted constructor of
'std::unique_ptr<bar, std::default_delete<bar> >'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:75:8: note: in instantiation of function template specialization
'std::_Construct<std::unique_ptr<bar, std::default_delete<bar> >, const std::unique_ptr<bar, std::default_delete<bar> > &>' requested here
std::_Construct(std::__addressof(*__cur), *__first);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:117:2: note: in instantiation of function template specialization
'std::__uninitialized_copy<false>::__uninit_copy<const std::unique_ptr<bar, std::default_delete<bar> > *, std::unique_ptr<bar, std::default_delete<bar> > *>'
requested here
__uninit_copy(__first, __last, __result);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_uninitialized.h:258:19: note: in instantiation of function template specialization
'std::uninitialized_copy<const std::unique_ptr<bar, std::default_delete<bar> > *, std::unique_ptr<bar, std::default_delete<bar> > *>' requested here
{ return std::uninitialized_copy(__first, __last, __result); }
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:1204:11: note: in instantiation of function template specialization
'std::__uninitialized_copy_a<const std::unique_ptr<bar, std::default_delete<bar> > *, std::unique_ptr<bar, std::default_delete<bar> > *, std::unique_ptr<bar,
std::default_delete<bar> > >' requested here
std::__uninitialized_copy_a(__first, __last,
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:368:2: note: in instantiation of function template specialization
'std::vector<std::unique_ptr<bar, std::default_delete<bar> >, std::allocator<std::unique_ptr<bar, std::default_delete<bar> > > >::_M_range_initialize<const
std::unique_ptr<bar, std::default_delete<bar> > *>' requested here
_M_range_initialize(__l.begin(), __l.end(),
^
test.cpp:17:12: note: in instantiation of member function 'std::vector<std::unique_ptr<bar, std::default_delete<bar> >, std::allocator<std::unique_ptr<bar,
std::default_delete<bar> > > >::vector' requested here
return { std::move( std::unique_ptr<bar>(new bar()) ) };
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/unique_ptr.h:273:7: note: function has been explicitly marked deleted here
unique_ptr(const unique_ptr&) = delete;
^
1 error generated.
The situations doesn't seem to be any better with g++ 4.8:
$ g++-4.8 -std=c++11 test.cpp -o xtest
In file included from /usr/include/c++/4.8/memory:64:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<bar>; _Args = {const std::unique_ptr<bar, std::default_delete<bar> >&}]’:
/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 = const std::unique_ptr<bar>*; _ForwardIterator = std::unique_ptr<bar>*; 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 = const std::unique_ptr<bar>*; _ForwardIterator = std::unique_ptr<bar>*]’
/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 = const std::unique_ptr<bar>*; _ForwardIterator = std::unique_ptr<bar>*; _Tp = std::unique_ptr<bar>]’
/usr/include/c++/4.8/bits/stl_vector.h:1206:27: required from ‘void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::unique_ptr<bar>*; _Tp = std::unique_ptr<bar>; _Alloc = std::allocator<std::unique_ptr<bar> >]’
/usr/include/c++/4.8/bits/stl_vector.h:369:36: required from ‘std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = std::unique_ptr<bar>; _Alloc = std::allocator<std::unique_ptr<bar> >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::unique_ptr<bar> >]’
test.cpp:17:59: required from here
/usr/include/c++/4.8/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 = bar; _Dp = std::default_delete<bar>]’
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
In file included from /usr/include/c++/4.8/memory:81:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/unique_ptr.h:273:7: error: declared here
unique_ptr(const unique_ptr&) = delete;
^
According to this answer and the comments, this shouldn't be happening on these compilers, but I'm not doing exactly the same: I'm trying to initialize the vector with an initializer list.
Any idea what needs to happen in order for this code to build correctly?
The used of the braced-init-list in the return statement within getVector
return { std::move( std::unique_ptr<bar>(new bar()) ) };
results in a call to the std::vector<T> constructor that takes an initializer_list<T> argument. Even though you're moving the unique_ptr, an initializer_list only allows const access to its elements, due to which the vector will attempt to copy the unique_ptr, leading to the error you see.
You can fix the error by resorting to a more verbose manner of constructing the vector
vtype getVector()
{
vtype v;
v.push_back(std::unique_ptr<bar>(new bar()));
return v;
}
Live demo
For curiosity's sake, it is possible to construct a vector from an array of move-only objects, but you need to go through std::move_iterator to move the elements.
vtype getVector()
{
std::unique_ptr<bar> arr[] = {std::unique_ptr<bar>(new bar())};
return {std::make_move_iterator(std::begin(arr)),
std::make_move_iterator(std::end(arr))};
}
your vtype is a vector of unique pointers and you returning to it a unique pointer.
since you are doing the move in the constructor foo you dont need to return a move
take a look to this code:
#include <memory> // for std::unique_ptr
#include <utility> // for std::move
#include <vector> // for std::vector
struct bar {};
using vtype = /*std::vector<*/std::unique_ptr<bar>/*>*/;
struct foo
{
foo(vtype v) : _v(std::move(v)) { }
private:
vtype _v;
};
vtype getVector()
{
return /*{ std::move(*/ std::unique_ptr<bar>(new bar()) /*) }*/;
};
int main()
{
foo f(std::move(getVector()));
};
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.