I wrote an unit test with hippomocks, but got error while compiling it.
The compiler is VS 2010.
How can I fix it ?
#include "hippomocks.h"
#include <functional>
using namespace HippoMocks;
struct A
{
virtual void f(std::function<void (int)> arg);
};
int main(void)
{
MockRepository mock;
A* aptr = mock.Mock<A>();
mock.ExpectCall(aptr, A::f); // error
return 0;
}
The output is :
main.cpp
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\xlocale(323) : wa
rning C4530: C++ exception handler used, but unwind semantics are not enabled. S
pecify /EHsc
c:\users\cong\project\test\test\hippomocks.h(466) : error C2593: 'operator <<' i
s ambiguous
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\ostream(2
06): could be 'std::basic_ostream<_Elem,_Traits> &std::basic_ostream<_Elem,_Trai
ts>::operator <<(std::_Bool)'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
c:\users\cong\project\test\test\hippomocks.h(441): or 'std::ostrea
m &HippoMocks::operator <<(std::ostream &,const HippoMocks::NotPrintable &)'
while trying to match the argument list '(std::ostream, std::tr1::functi
on<_Fty>)'
with
[
_Fty=void (int)
]
c:\users\cong\project\test\test\hippomocks.h(463) : while compiling clas
s template member function 'void HippoMocks::printArg<T>::print(std::ostream &,T
,bool)'
with
[
T=std::tr1::function<void (int)>
]
c:\users\cong\project\test\test\hippomocks.h(614) : see reference to cla
ss template instantiation 'HippoMocks::printArg<T>' being compiled
with
[
T=std::tr1::function<void (int)>
]
Enhancing #dascandy's comment here is how his method can look like. Place it after including hippomocks.h:
template<>
struct printArg<std::function<void (int)> >
{
static inline void print(std::ostream &os, std::function<void (int)> arg, bool withComma)
{
if (withComma)
{
os << ",";
}
if (arg)
{
os << "true";
}
else
{
os << "false";
}
}
};
Note that I didn't test this very example but rather took our solution and adapted the type to the original post's example. I'd be happy to know whether this works for you.
Related
I have a vector array for classes and im making a method that can delete the classes from that array, using std::remove(). The problem is Weapon (the class) doesn't have an operator == that std::remove needs to compare the elements.
the code:
class Weapon {
public:
std::string name;
Weapon(std::string x) {
name = x;
}
Weapon() {}
};
std::vector<Weapon> inventory{};
void removeInventory(Weapon x) {
if (inventorySize != 0) {
auto deleteFromInc = inventory.erase(std::remove(std::begin(inventory), std::end(inventory), x), std::end(inventory));
if (deleteFromInc != std::end(inventory)) {
std::cout << "Item didn't delete\n";
} else {
if (heldWeapon.name == x.name) {
heldWeapon = Weapon();
}
inventorySize = inventory.size();
std::cout << "Item deleted\n";
}
} else {
std::cout << "You have no items\n";
}
}
the error:
Rebuild started...
1>------ Rebuild All started: Project: rpag, Configuration: Debug Win32 ------
1>rpag.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xmemory(1945,1): error C2678: binary '==': no operator found which takes a left-hand operand of type 'Weapon' (or there is no acceptable conversion)
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared\guiddef.h(192,15): message : could be 'bool operator ==(const GUID &,const GUID &)' [found using argument-dependent lookup]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xmemory(1945,1): message : while trying to match the argument list '(Weapon, const _Ty)'
1> with
1> [
1> _Ty=Weapon
1> ]
1>C:\Users\alber\source\repos\rpag\rpag\rpag.cpp(89): message : see reference to function template instantiation '_FwdIt std::remove<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>,Weapon>(_FwdIt,const _FwdIt,const _Ty &)' being compiled
1> with
1> [
1> _FwdIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Weapon>>>,
1> _Ty=Weapon
1> ]
1>Done building project "rpag.vcxproj" -- FAILED.
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
This is my first question! I hope everything is clear.
std::remove needs operator== (this is requirement of c++ standart library). And you can adds the operator into your class, or use std::remove_if - it use predicate - external function for comparison.
There is third way: you can erase items from vector manually: for (...) { erase ...}
#include <thread>
#include <iostream>
#include <functional>
struct C
{
void printMe() const
{}
};
struct D
{
void operator()() const
{}
};
int main()
{
D d;
std::thread t9(std::ref(d)); // fine
t9.join();
C c;
std::thread t8(&C::printMe, std::ref(c)); // error in VS2015
t8.join();
/*
1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr/xthread(238): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr/xthread(238): note: With the following template arguments:
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr/xthread(238): note: '_Callable=void (__thiscall C::* )(void) const'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thr/xthread(238): note: '_Types={std::reference_wrapper<C>}'
*/
}
http://ideone.com/bxXJem built without problems
Is the following code correct?
std::thread t8(&C::printMe, std::ref(c));
No, it doesn't compile. To compile it and make run it you need:
1) It needs to set the method printMe as a static method to send an its address (printMe's address), otherwise you are sending a relative address to instance C.
2) At the moment of create the thread t8, you are sending a reference to object C as an argument but the function printMe doesn't have arguments, So you need declare the argument into the printMe method.
3) As #cpplearner told you, send the pointer of the method as: std::thread t8(&C::printMe, &c);.
The resulting code is:
#include <thread>
#include <iostream>
#include <functional>
struct C
{
static void printMe(C* ref)
{
std::cout << "Address of C ref: " << std::hex << ref << std::endl;
}
};
struct D
{
void operator()() const
{
std::cout << "Operator D" << std::endl;
}
};
int main()
{
D d;
std::thread t9(std::ref(d)); // fine
t9.join();
C c;
std::thread t8(&C::printMe, &c); // Compile in VS2015
t8.join();
std::cout << "END" << std::endl;
}
And the output is:
I am trying to use unique_ptr to manage my memory, and VS2013 seems to be giving me trouble when I think it shouldn't be.
It would seem that the compiler is for whatever reason trying to access a deleted copy constructor when it really should have no reason to do so.
This is what one of my classes looks like:
class Mesh
{
public:
Mesh(oglplus::Program* program, const std::vector<Vertex>& vertices,
const std::vector<GLuint>& indices);
void draw();
private:
const oglplus::Program* _program;
std::vector<Vertex> _vertices;
std::vector<GLuint> _indices;
oglplus::Buffer _faceBuffer;
oglplus::Buffer _vertexBuffer;
oglplus::VertexArray _vao;
};
class Model
{
public:
Model(std::string filename, oglplus::Program* program);
void draw();
private:
const oglplus::Program* _program;
std::vector<std::unique_ptr<Mesh>> _meshes;
};
The issue is with the line
std::vector<std::unique_ptr<Mesh>> _meshes;
it starts spewing things like
2>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(593): error C2280: 'std::unique_ptr<Model::Mesh,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
2> with
2> [
2> _Ty=Model::Mesh
2> ]
2> c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr<Model::Mesh,std::default_delete<_Ty>>::unique_ptr'
2> with
2> [
2> _Ty=Model::Mesh
2> ]
2> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(592) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
2> with
2> [
2> _Ty=std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>
2> ]
2> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(723) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
2> with
2> [
2> _Ty=std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>
2> ]
2> c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(572) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
2> with
2> [
2> _Ty=std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>
2> ]
2> c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(650) : see reference to class template instantiation 'std::is_empty<_Alloc>' being compiled
2> with
2> [
2> _Alloc=std::allocator<std::unique_ptr<Model::Mesh,std::default_delete<Model::Mesh>>>
2> ]
2> c:\users\vitali\projects\3d-stg\source\model\model.hpp(45) : see reference to class template instantiation 'std::vector<std::unique_ptr<Model::Mesh,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
2> with
2> [
2> _Ty=Model::Mesh
2> ]
2> model.cpp
I am not using std::vector::resize() or anything like that (in-fact I commented out all uses of my _meshes vector, and even tried commenting the implementation out completely to no avail), so I don't understand why the compiler is giving me issues.
Does anybody have any ideas?
Thank you Preetish Kakkar for finding the issue. It turns out it was an issue with compiler generated functions implicitly using the copy constructor and operator= of the Mesh class forcing the compiler to try and use deleted functions.
I reproduced your problem, below is sample code.
#include <vector>
#include <memory>
class Mesh
{
public:
Mesh() {}
void draw() {}
private:
};
class Model
{
public:
Model() {}
void draw() {}
private:
typedef std::unique_ptr<Mesh> MeshUniquePtr;
std::vector<MeshUniquePtr> _meshes;
};
int _tmain(int argc, _TCHAR* argv[])
{
Model m;
Model m1;
m = m1; // causes error as you can't copy unique ptr
return 0;
}
The problem is at some point you are trying to copy two model object which can't be done as unique_ptr is not copyable.
#include <iostream>
using namespace std;
template < class T >
void swap (T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
int main ()
{
char a = 'a';
char b = 'b';
swap (a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
return 0;
}
the code can not be compiled under linux KDE command line (gcc compiler).
however if I change "using namespace std" into "using std::cout; using std::cin using std::endl" the program can be compiled and run well. what's wrong with it?
Thank you very much
Your definition of swap is conflicting with the already existing definition of std::swap when you bring std in the global namespace using using namespace.
Note that the conflict occurs when you try to instantiate the template, you can use
::swap (a, b);
to choose explicitly your definition.
Here is what VC++ says:
error C2668: 'swap' : ambiguous call to overloaded function
1> c:\lisp\other\test_meth\test_meth.cpp(7): could be 'void swap<char>(T &,T &)'
1> with
1> [
1> T=char
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(100): or 'void std::swap<char>(_Ty &,_Ty &)'
1> with
1> [
1> _Ty=char
1> ]
1> while trying to match the argument list '(char, char)'
The problem is: std namespace already contains the template function swap.
The meaning of the VC++ compiler warning C4250 'class1' : inherits 'class2::member' via dominance is clear to me. (But see here for an explanation.)
I have currently the problem that I get this warning when serializing a class hierarchy that has an abstract base class with boost::serialization (1.44.0).
Please note that my classes do not form any kind of diamond-like inheritance hierarchy that could cause this warning, but the warning is caused by the instantiation of boost::detail::is_virtual_base_of_impl<...> when serializing instances of derived classes. (Which seems to be using is_virtual_base_of from Boost.TypeTraits.)
Here is a minimal code sample to reproduce the warning on Visual Studio 2005. Note that the code should be dropped as-is into one cpp-file and it should compile.
Note also the two points in the code that I have marked by comments that trigger the warning. If BOOST_CLASS_EXPORTis not used then the warning is not triggerd, but more interestingly the warning is also not triggered, if the derived class does not use virtual inheritance! (So maybe I do not understand C4250 after all.)
// -- std includes --
#include <iostream>
#include <sstream>
#include <string>
// -- boost serialization --
#define BOOST_SERIALIZATION_DYN_LINK
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>
// Base with serialization support
struct Base
{
virtual ~Base() {};
virtual void DoStuff() const {
std::cout << "Base#[" << static_cast<const void*>(this) << "]::DoStuff() called\n";
}
template<class Archive> // serialization support!
void serialize(Archive & ar, const unsigned int file_version) { /*empty*/ }
};
// (The only) Specific class with ser. support
struct Concrete2 : virtual/*!C4250!*/ public Base
{
virtual void DoStuff() const {
std::cout << "Concrete2#[" << static_cast<const void*>(this) << "]::DoStuff() called\n";
}
template<class Archive> // serialization support!
void serialize(Archive & ar, const unsigned int ver) {
ar & boost::serialization::base_object<Base>(*this);
// This is just a test - no members neccessary
std::cout << "Concrete2::serialize!" << typeid(ar).name() << "\n";
}
};
// Without guid export -> *no* C4250, even *with* virtual inheritance
// (however, can't be serialized via base class pointer anymore)
BOOST_CLASS_EXPORT(Concrete2);
BOOST_CLASS_TRACKING(Concrete2, boost::serialization::track_never);
int main() {
using namespace std;
Concrete2 obj1;
obj1.DoStuff();
// The following test code is not neccessary to generate the warning ...
// (but is neccessary to show if base-pointer serialization works at runtime)
Base* ref1 = &obj1;
ostringstream out_buf;
boost::archive::text_oarchive out_archive(out_buf);
out_archive << ref1;
const string buf = out_buf.str();
cout << "Serialized obj:\n~~~~\n";
cout << buf;
cout << "\n~~~~~\n";
std::istringstream in_buf(buf);
boost::archive::text_iarchive in_archive(in_buf);
// Concrete2 obj2;
Base* ref2;
in_archive >> ref2;
if(ref2)
ref2->DoStuff();
delete ref2;
}
And here is the compiler warning (ugh!):
1>...\boost_library-1_44_0\boost\type_traits\is_virtual_base_of.hpp(61) : warning C4250: 'boost::detail::is_virtual_base_of_impl<Base,Derived,tag>::X' : inherits 'Concrete2::Concrete2::DoStuff' via dominance
1> with
1> [
1> Base=type,
1> Derived=Concrete2,
1> tag=boost::mpl::bool_<true>
1> ]
1> ...\boostserializewarningtest\vbc.cpp(27) : see declaration of 'Concrete2::DoStuff'
...
1> ...\boost_library-1_44_0\boost\mpl\eval_if.hpp(40) : see reference to class template instantiation 'boost::mpl::if_<T1,T2,T3>' being compiled
1> with
1> [
1> T1=boost::is_virtual_base_of<type,Concrete2>,
1> T2=boost::mpl::identity<boost::serialization::void_cast_detail::void_caster_virtual_base<Concrete2,type>>,
1> T3=boost::mpl::identity<boost::serialization::void_cast_detail::void_caster_primitive<Concrete2,type>>
1> ]
1> ...\boost_library-1_44_0\boost\serialization\void_cast.hpp(279) : see reference to class template instantiation 'boost::mpl::eval_if<C,F1,F2>' being compiled
1> with
1> [
1> C=boost::is_virtual_base_of<type,Concrete2>,
1> F1=boost::mpl::identity<boost::serialization::void_cast_detail::void_caster_virtual_base<Concrete2,type>>,
1> F2=boost::mpl::identity<boost::serialization::void_cast_detail::void_caster_primitive<Concrete2,type>>
1> ]
1> ...\boost_library-1_44_0\boost\serialization\base_object.hpp(68) : see reference to function template instantiation 'const boost::serialization::void_cast_detail::void_caster &boost::serialization::void_cast_register<Derived,Base>(const Derived *,const Base *)' being compiled
1> with
1> [
1> Derived=Concrete2,
1> Base=type
1> ]
...
1> ...\boost_library-1_44_0\boost\serialization\export.hpp(128) : while compiling class template member function 'void boost::archive::detail::`anonymous-namespace'::guid_initializer<T>::export_guid(boost::mpl::false_) const'
1> with
1> [
1> T=Concrete2
1> ]
1> ...\boostserializewarningtest\vbc.cpp(40) : see reference to class template instantiation 'boost::archive::detail::`anonymous-namespace'::guid_initializer<T>' being compiled
1> with
1> [
1> T=Concrete2
1> ]
The reason is in fact the is_virtual_base_of check from boost type traits. This check-construct will generate warning C4250 if the check is successful, as can be seen by this example:
...
struct base {
virtual void mf() { };
};
struct derived_normal : public base {
virtual void mf() { };
};
struct derived_virt : virtual public base {
virtual void mf() { };
};
int main() {
using namespace std;
cout << "boost::is_virtual_base_of<base, derived_normal>::value reports: ";
// The following line DOES NOT cause C4250
cout << boost::is_virtual_base_of<base, derived_normal>::value << endl;
cout << "boost::is_virtual_base_of<base, derived_virt> reports: ";
// The following line causes C4250:
cout << boost::is_virtual_base_of<base, derived_virt>::value << endl;
...
FWIW, the usage of this type-traits tool in boost serialization goes like this:
macro BOOST_EXPORT_CLASS ->
macro BOOST_CLASS_EXPORT_IMPLEMENT ->
struct guid_initializer (in export.hpp) ->
(...) void_cast.hpp / void_cast_register -> is_virtual_base_of is used here
As far as I can tell the warning is completely harmless in this case and can be prevented by wrapping the header in:
#pragma warning( push )
#pragma warning( disable : 4250 ) // C4250 - 'class1' : inherits 'class2::member' via dominance
#include ...
#pragma warning( pop ) // C4250