Replacing a set object with a new set object - c++

I have a class with a private field:
std::set<std::string> _channelNames;
.. and an optional setter function:
void setChannelNames(std::set channelNames);
In the setter function, how do I replace the private _channelNames field with the one passed from the setter function?
I tried:
void Parser::setChannelNames(std::set channelNames) {
this->_channelNames = channelNames;
}
But this produced an error in VS2005:
Error 2 error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::set' (or there is no acceptable conversion) parser.cpp 61
I am definitely a C++ novice, and expect that I should be doing some pointer work here instead.
Any quick tips?
Thanks!

You just have to specialize template. You cannot use std::set without specialization.
void Parser::setChannelNames(const std::set<std::string> & channelNames) {
this->_channelNames = channelNames;
}

Related

Error C2679 binary '<<': no operator found which takes a right-hand operand of type 'T'

I try to compile the following code:
class CFileOperations
{
...
template <typename T>
inline void load_and_save_data(std::fstream* stream, T& value, const EOperation operation)
{
switch (operation) {
case EOperation::OpSave:
*stream << value; <-- here
break;
case EOperation::OpLoad:
*stream >> value; <-- and here
break;
}
}
...
};
I get the following errors:
Error C2679 binary '<<': no operator found which takes a right-hand operand of type 'T' (or there is no acceptable conversion)
Error C2679 binary '>>': no operator found which takes a right-hand operand of type 'T' (or there is no acceptable conversion)
For example, I use it this way, with number being an 'int':
this->load_and_save_data(stream, number, operation);
I'm using Visual C++ 2019.
What's the root cause, and how to solve it. Any idea ?
My bad, one of the calls was with a 'class enum'. Of course, >> and << are not defined for it.
For #cdhowie, here are two examples of the resulting simplicity (with the help of load_and_save_data template methods):
Here mMembers is a std::unorderedmap (cf. save_and_load_data in the question above, I have also one for the starndard containers):
void CHexArea::load_and_save()
{
this->load_and_save_data((char&)mColor);
this->load_and_save_data(mTouchLeft);
this->load_and_save_data(mTouchRight);
this->load_and_save_data(mTouchBottom);
this->load_and_save_data(mTouchTop);
this->load_and_save_data(mMembers);
}
Here, in preferences, there are two versions of files:
void CHexPreferences::load_and_save()
{
if( this->is_loading() ) {
this->reset(); // version's forward compatibility
}
int version = 2;
this->load_and_save_data(version);
this->load_and_save_data(mBoardOrientation);
this->load_and_save_data(mBoardSize);
this->load_and_save_data(mComputerStarts);
this->load_and_save_data(mComputerInitialTurns);
if( version >= 2) {
this->load_and_save_data(mComputerTilesPerTurn);
}
this->load_and_save_data(mDebugFlags);
}
Simple and clear.
Of course, there are two methods (load() and save()) that are the outer interface and calls those here above, but: 1. They are part of a library (no need to rewrite them, OO as usual) and 2. The core of the load/save is written only once in load_save_data, with the advantage of simplicity, and having corresponding load and save code (types, order...).
Of course, there are cons, but I hope you'll see that it may make sense for some people to think that there are (IMHO very strong) pros as well.
The rest is a matter of taste.

How to remove function pointer from std::deque by val?

I am using std::deque to keep callback functions.
Everything works perfectly except removing a specific callback.
typedef std::function<void(void)> cb_Action;
std::deque<cb_Action> actionCallbacks;
I can Add items one by one or clear all of them without any problems.
But I cannot remove a specific callback from the deque variable.
actionCallbacks.erase ( std::remove(actionCallbacks.begin(), actionCallbacks.end(), callbackToRemove), actionCallbacks.end());
It gives compile time error:
binary '==': no operator found which takes a left-hand operand of type:'std::function<void(void)>' (or there is no acceptable conversion)
So, how can I remove a specific cb_Action?
If you deal with usual functions you can do something like this based on std::function::target:
void callback_1(void) {}
void callback_2(void) {}
actionCallbacks = {
std::function<void(void)>(callback_1),
std::function<void(void)>(callback_2),
std::function<void(void)>(callback_1)
};
actionCallbacks.erase(
std::remove_if(actionCallbacks.begin(), actionCallbacks.end(), [](cb_Action action) {
return (*action.target<void(*)(void)>() == callback_1);
}),
actionCallbacks.end()
);
Here all items with callback_1 inside are removed.

Overloaded methods - (Error C2664: Cannot convert from vector<T> to T)

I'm trying to call an overloaded method from the other overloaded member. I am getting an error C2664: Cannot convert argument 2 from std::vector<PK_BODY_T*, std::allocator<_Other>> to PK_BODY_T
Code:
std::vector<PK_BODY_t*> FillHoles(std::vector<std::vector<PK_EDGE_t>> holes, PK_BODY_t inputBody)
{
std::vector<PK_BODY_t*> vectorBodies;
PK_BODY_t *pointerInputBody = new PK_BODY_t(inputBody);
vectorBodies.push_back(pointerInputBody);
std::vector<PK_BODY_t*> returnVector;
returnVector = FillHoles(holes, vectorBodies); //<-- ERROR HERE. Calling overloaded method.
delete pointerInputBody;
return returnVector;
}
/* overloaded version of FillHoles
*/
std::vector<PK_BODY_t*> FillHoles(std::vector<std::vector<PK_EDGE_t>> holes, std::vector<PK_BODY_t*> inputBody)
{
//...
std::vector<PK_BODY_t*> fillHoleOutput = FillOneHole(currentBody, currentHole);
return fillHoleOutput;
}
It appears as if the first method is trying to call itself here, instead of the second overloaded method. How do I force it to use the second method?
You did not show how the functions are declared and in what scopes whether one function hides other function.
But in any case just declare the second overloaded function inside the first overloaded function
std::vector<PK_BODY_t*> FillHoles(std::vector<std::vector<PK_EDGE_t>> holes, PK_BODY_t inputBody)
{
std::vector<PK_BODY_t*> FillHoles(std::vector<std::vector<PK_EDGE_t>> holes, std::vector<PK_BODY_t*> inputBody);
//...
C++ files are compiled from top to bottom. From the vantage point of the top method, it cannot 'see' the second method, because it has not been compiled yet (as the second method is after the first method).
You must either declare methods in a header .h file, or forward declare the methods at the top of the .cpp file.
http://www.learncpp.com/cpp-tutorial/19-header-files/
http://www.learncpp.com/cpp-tutorial/17-forward-declarations/

Using find_if within instance method

I have an instance method that populates a vector of strings. I am trying to find the one vector entry that contains a specific substring (for now, that substring is fixed - simple).
I have a .h:
namespace Data
{
namespace Shared
{
class Logger
{
public:
bool FindLogDirectoryPredicate(const string &str);
int GetLogDirectory(string logConfigFile, string& logDirectory);
...
}
}
}
and .cpp:
#include <algorithm>
#include <vector>
#include "Logger.h"
bool Logger::FindLogDirectoryPredicate(const string &str)
{
// Return false if string found.
return str.find("File=") > 0 ? false : true;
}
int Logger::GetLogDirectory(string logConfigFile, string& logDirectory)
{
vector<string> fileContents;
...
vector<string>::iterator result = find_if(fileContents.begin(), fileContents.end(), FindLogDirectoryPredicate);
...
}
Compiling this in Visual Studio 2010, I receive:
Error 7 error C3867: 'Data::Shared::Logger::FindLogDirectoryPredicate': function call missing argument list; use '&Data::Shared::Logger::FindLogDirectoryPredicate' to create a pointer to member Logger.cpp 317 1 Portability
Throwing an & in front of the function ref in the find_if call then results in:
Error 7 error C2276: '&' : illegal operation on bound member function expression Logger.cpp 317 1 Portability
I did try to put the predicate function outside the class, but that didn't seem to work - gave me a function not found error. Tried qualifying the predicate with the class name... that gave me a different error in algorithm (header):
Error 1 error C2064: term does not evaluate to a function taking 1 arguments c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm 83 1 Portability
The example I was following from here seems to indicate that this is relatively simple.... so what am I doing wrong?
The problem is that FindLogDirectoryPredicate is an instance method: it's not enough to specify its name, you somehow have to specify which object that method should be called on. Now the answer to this question is obvious to us (this), but not to the compiler.
The classic way to do this is with
find_if(fileContents.begin(),
fileContents.end(),
bind1st(mem_fun(&Logger::FindLogDirectoryPredicate), this));
What's going on here?
mem_fun "converts a member function to a function object". That is, it creates an instance of a type (what type exactly is unspecified, but we don't care) that exposes operator() (this is what we do care about!). This operator expects the first parameter to be a pointer to an instance of the type that defines the member function; here, that would be an instance of Logger.
bind1st then takes this function object that takes two parameters (first is the pointer to instance, second is the original const string & parameter) and returns a different function object that takes just one parameter (the const string &). The other parameter is fixed to the value of bind1st's second argument (this).
Alternatively, if you can make FindLogDirectoryPredicate static then there's no longer any need to specify which instance to call it on, so the problem will automatically go away.
Make the predicate static
class Logger
{
public:
static bool FindLogDirectoryPredicate(const string &str);
}
Or perhaps, use a lambda.
result = std::find_if(begin(), end(), [&this] (const std::string& s)
{ return FindLogDirectoryPredicate(s); } );
You can also use a std::mem_fun (and related <functional> stuff) if you must use C++98/C++03
result = std::find_if(begin(), end(),
std::bind1st(std::mem_fun(&Logger::FindLogDirectoryPredicate), this) );
Make your predicate a static class member.
static bool FindLogDirectoryPredicate(const string &str);

issue returning CArray

I am trying to return a CArray from a function and trying to call the function from another class
short ListMaker::RetArray(CString szName, CArray<CString, CString&> &szarr_Names) {
szarr_Names.Add(szName);
return 0;
}
int main() {
//..
CArray<CString, CString&> myArray;
ListMaker LM;
short nCode = LM.RetArray(L"Name", myArray);
//..
}
I am getting following errors:
Error 1 error C2664: 'RetArray' : cannot convert parameter 2 from 'CArray<TYPE,ARG_TYPE>' to 'CArray<TYPE,ARG_TYPE>'
Error 2 error C2511: 'short RetArray(CString,CArray<TYPE,ARG_TYPE> &)' : overloaded member function not found in 'ListMaker'
Please tell me the correct way to define and access the return value of the CArray.
Erm, frist of all if RetArray is a member of ListMaker class and you call it from main(), you cannot call it like this: short nCode = RetArray(L"Name", myArray);
If RetArray is a static member, use short nCode = ListMaker::RetArray(L"Name", myArray);. It it's non-static, use instance, short nCode = listMakerInstance.RetArray(L"Name", myArray);.
Check your header file for RetArray declaration in ListMaker class. It might differ from the implementation in your cpp file, hence you get the C2511 error.
You cannot store a reference in an array type, and CArray is to be absolutely avoided at all costs as it uses memcpy to resize and not copy construction, breaking your code the instant you need something with a useful constructor.
I think the problem is in CString&, try using CArray<CString, LPCTSTR> instead.