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 ...}
Related
I'm doing a little file watcher in C++, but after some refactoring I got stuck with some problem. Mainly I understand what's the problem. I call a function which is actually not a function, but I cannot find such thing. All answers say that there is some name which is called as a function.
Here is my header:
#ifndef FILEWATCHER_H
#define FILEWATCHER_H
#include <unordered_map>
#include <filesystem>
namespace fs = std::filesystem;
class FileWatcher
{
size_t currentNumberOfFiles = 0;
fs::path pathToWatch;
std::unordered_map<fs::path, fs::file_time_type> pathsMap;
std::string currentTime();
public:
FileWatcher(fs::path path);
void start();
};
#endif
And the .cpp file:
#pragma warning(disable : 4996)
#include "FileWatcher.h"
#include "Event.h"
std::string FileWatcher::currentTime()
{
auto now = std::chrono::system_clock::now();
std::time_t nowTime = std::chrono::system_clock::to_time_t(now);
std::string currentSystemTime = std::ctime(&nowTime);
return currentSystemTime;
}
FileWatcher::FileWatcher(fs::path pathToWatch)
{
this->pathToWatch = pathToWatch;
//create a map with last modification of a given file in the directory
for (auto& file : fs::directory_iterator(this->pathToWatch))
{
pathsMap.emplace(file.path(), fs::last_write_time(file));
}
}
void FileWatcher::start()
{
while (true)
{
currentNumberOfFiles = std::distance(fs::directory_iterator(pathToWatch), fs::directory_iterator());
for (std::unordered_map<fs::path, fs::file_time_type>::iterator it = pathsMap.begin(); it != pathsMap.end(); )
{
if (!fs::exists(it->first))
{
if (currentNumberOfFiles < pathsMap.size())
{
//std::cout << "File was erased" << std::endl;
it = pathsMap.erase(it);
//FileType fileType = ( ? FileType::FILE : FileType::DIRECTORY);
std::string time = this->currentTime();
Event event(EventType::DELETED, FileType::FILE, it->first, time);
event.printEvent();
}
else
{
//std::cout << "Renamed" << std::endl;
it = pathsMap.erase(it);
}
}
else
{
it++;
}
}
for (auto& file : fs::directory_iterator(pathToWatch))
{
if (!pathsMap.count(file.path()))
{
//std::cout << "File has been created" << std::endl;
pathsMap.emplace(file.path(), fs::last_write_time(file));
}
else
{
if (pathsMap.at(file.path()) != fs::last_write_time(file))
{
//std::cout << "File has been modified" << std::endl;
pathsMap.at(file.path()) = fs::last_write_time(file);
}
}
}
}
}
Here is the error list:
1st error:
Severity Code Description Project File Line Column Category Source Suppression State
Error C2056 illegal expression ProgrammingAssignment C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash 130 44 Build
2nd error:
Severity Code Description Project File Line Column Category Source Suppression State
Error C2064 term does not evaluate to a function taking 1 arguments ProgrammingAssignment C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash 131 53 Build
This is the place error list refer to in the filesystem library.
template <class _Hasher, class _Kty>
_INLINE_VAR constexpr bool _Nothrow_hash = noexcept(
static_cast<size_t>(_STD declval<const _Hasher&>()(_STD declval<const _Kty&>())));
This is the error output:
Build started...
1>------ Build started: Project: ProgrammingAssignment, Configuration: Debug Win32 ------
1>FileWatcher.cpp
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(131,53): error C2064: term does not evaluate to a function taking 1 arguments
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(155): message : see reference to variable template 'const bool _Nothrow_hash<std::hash<std::filesystem::path>,std::filesystem::path>' being compiled
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(155): message : while compiling class template member function 'size_t std::_Uhash_compare<_Kty,_Hasher,_Keyeq>::operator ()<_Kty>(const _Keyty &) noexcept(<expr>) const'
1> with
1> [
1> _Kty=std::filesystem::path,
1> _Hasher=std::hash<std::filesystem::path>,
1> _Keyeq=std::equal_to<std::filesystem::path>,
1> _Keyty=std::filesystem::path
1> ]
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(1218): message : see reference to variable template 'const bool _Nothrow_hash<std::_Umap_traits<std::filesystem::path,std::chrono::time_point<std::filesystem::_File_time_clock,std::chrono::duration<__int64,std::ratio<1,10000000> > >,std::_Uhash_compare<std::filesystem::path,std::hash<std::filesystem::path>,std::equal_to<std::filesystem::path> >,std::allocator<std::pair<std::filesystem::path const ,std::chrono::time_point<std::filesystem::_File_time_clock,std::chrono::duration<__int64,std::ratio<1,10000000> > > > >,0>,std::filesystem::path>' being compiled
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(1218): message : while compiling class template member function 'std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>> std::_Hash<std::_Umap_traits<_Kty,std::chrono::time_point<std::filesystem::_File_time_clock,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>>,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_Alloc,false>>::erase<std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>>,0>(std::_List_iterator<std::_List_val<std::_List_simple_types<_Ty>>>) noexcept(<expr>)'
1> with
1> [
1> _Ty=std::pair<const std::filesystem::path,std::filesystem::file_time_type>,
1> _Kty=std::filesystem::path,
1> _Hasher=std::hash<std::filesystem::path>,
1> _Keyeq=std::equal_to<std::filesystem::path>,
1> _Alloc=std::allocator<std::pair<const std::filesystem::path,std::filesystem::file_time_type>>
1> ]
1>C:\VisualStudio2019\VC\Tools\MSVC\14.28.29910\include\xhash(130,44): error C2056: illegal expression
1>Done building project "ProgrammingAssignment.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
The error messages are very difficult to read, but it basically boils down to a missing implementation of std::hash<std::filesystem::path>.
std::unordered_map uses hashes to order its elements. By default, it uses a specialization of std::hash on the map's key_type. However, the standard library does not provide a specialization of std::hash for std::filesystem::path, hence the errors.
So, if you want to use std::filesystem::path as the key_type of std::unordered_map, you have to either:
provide your own specialization of std::hash<std::filesystem::path>, eg:
template <>
class std::hash<fs::path>
{
public:
size_t operator()(const fs::path &path) const
{
return ... a hash of path ...;
}
};
class FileWatcher
{
...
std::unordered_map<fs::path, fs::file_time_type> pathsMap;
...
};
implement a custom class/struct with an operator() that takes a std::filesystem::path as input and returns a unique value as output. Then you can explicitly state that type in the std::unordered_map's Hash template parameter, eg:
struct MyPathHash
{
size_t operator()(const fs::path &path) const
{
return ... a hash of path ...;
}
};
class FileWatcher
{
...
std::unordered_map<fs::path, fs::file_time_type, MyPathHash> pathsMap;
...
};
Otherwise, use std::map instead. It uses operator< to order its elements, and std::filesytem::path has its own operator< implemented, eg:
...
#include <map>
class FileWatcher
{
...
std::map<fs::path, fs::file_time_type> pathsMap;
...
};
I was following a talk on YouTube by Kelvin Henney based on the idiom of Functional C++... About 50 minutes into the video he starts showing an example class structure that he named channel. Then he writes the simple fizzbuzz function and is going to pass that into a server like piece of code using threads. I'm using the code from his video which can be found here: Kevlin Henney - Functional C++
However, when I try to compile the program, Visual Studio is generating the C2661 compiler error pointing to std::tuple... which is coming from the std::tread's constructor within my code.
main.cpp
#include <iostream>
#include <exception>
#include <string>
#include <thread>
#include "server.h"
std::string fizzbuzz(int n) {
return
n % 15 == 0 ? "FizzBuzz" :
n % 3 == 0 ? "Fizz" :
n % 5 == 0 ? "Buzz" :
std::to_string(n);
}
void fizzbuzzer(channel<int> & in, channel<std::string> & out) {
for (;;)
{
int n;
in.receive(n);
out.send(fizzbuzz(n));
}
}
int main() {
try {
channel<int> out;
channel<std::string> back;
std::thread fizzbuzzing(fizzbuzzer, out, back);
for (int n = 1; n <= 100; ++n) {
out << n;
std::string result;
back >> result;
std::cout << result << "\n";
}
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
server.h
#pragma once
#include <condition_variable>
#include <queue>
#include <mutex>
#include <iostream>
template<typename ValueType>
class receiving;
template<typename ValueType>
class channel {
private:
std::mutex key;
std::condition_variable_any non_empty;
std::queue<ValueType> fifo;
public:
void send(const ValueType & to_send) {
std::lock_guard<std::mutex> guard(key);
fifo.push(to_send);
non_empty.notify_all();
}
bool try_receive(ValueType & to_receive) {
bool received = false;
if (key.try_lock()) {
std::lock_guard<std::mutex> guard(key, std::adopt_lock);
if (!fifo.empty()) {
to_receive = fifo.front();
fifo.pop();
received = true;
}
}
return received;
}
void receive(ValueType & to_receive) {
std::lock_guard<std::mutex> guard(key);
non_empty.wait(
key,
[this] {
return !fifo.empty();
});
to_receive = fifo.front();
fifo.pop();
}
void operator<<(const ValueType & to_send) {
send(to_send);
}
receiving<ValueType> operator>>(ValueType & to_receive) {
return receiving(this, to_receive);
}
};
template<typename ValueType>
class receiving {
private:
channel<ValueType> * that;
ValueType & to_receive;
public:
receiving(channel<ValueType> * that, ValueType & to_receive)
: that(that), to_receive(to_receive)
{}
receiving(receiving && other)
: that(other.that), to_receive(other.to_receive)
{
other.that = nullptr;
}
operator bool() {
auto from = that;
that = nullptr;
return from && from->try_recieve(to_receive);
}
~receiving() {
if (that)
that->receive(to_receive);
}
};
I know that the code he is showing is only an example code, but I figured I would try it within my IDE while following the video to get a better understanding of his talk. I'd like to be able to compile this just to see the generated output, and to be able to step through the debugger and disassembler, but I've hit a roadblock at this point. I understand the generated compiler error, just not sure how to resolve it based on his code sample...
Here's the compiler error that is being generated:
1>------ Build started: Project: Computations, Configuration: Debug Win32 ------
1>main.cpp
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\memory(2539): error C2661: 'std::tuple<void (__cdecl *)(channel<int> &,channel<std::string> &),channel<int>,channel<std::string>>::tuple': no overloaded function takes 3 arguments
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\thread(46): note: see reference to function template instantiation 'std::unique_ptr<std::tuple<void (__cdecl *)(channel<int> &,channel<std::string> &),channel<int>,channel<std::string>>,std::default_delete<_Ty>> std::make_unique<std::tuple<void (__cdecl *)(channel<int> &,channel<std::string> &),channel<int>,channel<std::string>>,void(__cdecl &)(channel<int> &,channel<std::string> &),channel<int>&,channel<std::string>&,0>(void (__cdecl &)(channel<int> &,channel<std::string> &),channel<int> &,channel<std::string> &)' being compiled
1> with
1> [
1> _Ty=std::tuple<void (__cdecl *)(channel<int> &,channel<std::string> &),channel<int>,channel<std::string>>
1> ]
1>c:\users\skilz99\source\repos\computations\computations\main.cpp(31): note: see reference to function template instantiation 'std::thread::thread<void(__cdecl &)(channel<int> &,channel<std::string> &),channel<int>&,channel<std::string>&,void>(_Fn,channel<int> &,channel<std::string> &)' being compiled
1> with
1> [
1> _Fn=void (__cdecl &)(channel<int> &,channel<std::string> &)
1> ]
1>Done building project "Computations.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
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.
#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.
I just have a very basic class that gives with functions that return the winning team of a match.
here's team.cpp
class teams
{
string teamName;
string teamName2;
int score;
int score2;
public:
teams ();
void set_team1();
void set_team2();
string get_score()
{
if (score > score2)
{
return teamName;
}
else
{
return teamName2;
}
}
private:
void teams::set_team1(string teamName, int score)
{
this->teamName=teamName;
this->score=score;
}
void teams::set_team2(string teamName2, int score2)
{
this->teamName2=teamName2;
this->score2=score2;
}
};
and here's is the line where i'm getting the error in the main method. I'm trying to create a teams object.
firstTeam.set_team1(teamName, score);
firstTeam.set_team2(teamName2, score2);
Visual studio comes up and says "error: no instance of overloaded function "team::set_team1" matches the argument list".
What am I missing?
This is the exact error I get:
1>c:\users\lab8.cpp(31): error C2664: 'void teams::set_team1(std::string,int)' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'std::string'
1> with
1> [
1> _Ty=std::string
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>c:\users\lab8.cpp(32): error C2664: 'void teams::set_team2(std::string,int)' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'std::string'
1> with
1> [
1> _Ty=std::string
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1> Generating Code...
1>
1>Build FAILED.
error C2664: 'void teams::set_team1(std::string,int)' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'std::string'
From the error message, it is clear that first parameter isn't of type std::string. It is actually a std::vector. So,
firstTeam.set_team1(teamName, score); // Check what is the type of teamName
If you can see that teamName is actually a std::string, then check whether you are compiling the right file. Save the file and try again because the code you posted and the error message has no relation.
Compiler don't provide default constructor( constructor with no arguments ) in case your class overloads the constructor.
class teams
{
string teamName;
string teamName2;
int score;
int score2;
// ...
public:
teams( string t, int s ) : teamName(x), score(s)
// Initializer list
{}
};
But the I don't understand, why you have teamName2, score2 members as members of teams. What if there are 10 teams? Just have an instance for each team and compare them with other instances of teams.
You have declared the two methods without parameters. Convert:
void set_team1();
void set_team2();
into:
void set_team1(string, int);
void set_team2(string, int);