#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.
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 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.
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
Does anyone know why this will not compile? I've tried both VS 2008 and GCC 4.something and both spit out errors. It doesn't matter whether or not I'm referencing "ThisFunctionDoesNotCompile()".
I can workaround this by just passing 'InternalType' as a second template parameter to Base, but I'm still curious why this comes up as an error.
#include <iostream>
using namespace std;
class DataClass
{
public:
int m_data;
};
template<typename DerivedType>
class Base
{
public:
int ThisFunctionCompiles()
{
// No problems here.
typename DerivedType::InternalType temp;
temp.m_data = 5;
return temp.m_data;
}
// error C2039: 'InternalType' : is not a member of 'Derived<InInternalType>'
typename DerivedType::InternalType ThisFunctionDoesNotCompile()
{
return static_cast<DerivedType*>(this)->GetInternalData();
}
};
template<typename InInternalType>
class Derived : public Base<Derived<InInternalType> >
{
public:
typedef InInternalType InternalType;
InternalType GetInternalData()
{
return m_internalData;
}
private:
InternalType m_internalData;
public:
void SetInternalData( int newVal )
{
m_internalData.m_data = newVal;
}
};
int main()
{
Derived<DataClass> testDerived;
testDerived.SetInternalData( 3 );
cout << testDerived.GetInternalData().m_data << endl;
cout << testDerived.ThisFunctionCompiles() << endl;
// The compiler gives an error regardless of whether or not this is commented out.
//cout << testDerived.ThisFunctionDoesNotCompile().m_data << endl;
return 0;
}
These are the errors I get in VS 2008:
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(27) : error C2039: 'InternalType' : is not a member of 'Derived<InInternalType>'
1> with
1> [
1> InInternalType=DataClass
1> ]
1> e:\test\generaltestprogram\generaltestprogram\main.cpp(35) : see reference to class template instantiation 'Base<DerivedType>' being compiled
1> with
1> [
1> DerivedType=Derived<DataClass>
1> ]
1> e:\test\generaltestprogram\generaltestprogram\main.cpp(58) : see reference to class template instantiation 'Derived<InInternalType>' being compiled
1> with
1> [
1> InInternalType=DataClass
1> ]
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(27) : error C2146: syntax error : missing ';' before identifier 'ThisFunctionDoesNotCompile'
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(27) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(28) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>e:\test\generaltestprogram\generaltestprogram\main.cpp(28) : warning C4183: 'ThisFunctionDoesNotCompile': missing return type; assumed to be a member function returning 'int'
And these are what GCC gives me:
main.cpp: In instantiation of 'Base<Derived<DataClass> >':
main.cpp:96: instantiated from 'Derived<DataClass>'
main.cpp:119: instantiated from here
main.cpp:88: error: no type named 'InternalType' in 'class Derived<DataClass>'
At the time that the templated class Base is instantiated as a parent of the class Derived, the class Derived is not a complete type.
Since Base<Derived<DataClass> > is a parent class of Derived<DataClass>, it must be instantiated before Derived<DataClass> can be instantiated. So when the class Base<Derived<DataClass> > is built from the template, Derived<DataClass> behaves as if it were a forward declaration. And as you're probably aware, you can't reference members of incomplete types, nor can your forward-declare nested types, so you're out of luck here.
This, by the way, is why it's difficult to implement a properly covariant clone() method using templates. See here and here (mine).