Compile error for map operator [] - c++

Why do I get a compile error for "recMap[key] = rec;" in the below code but the equivalent statements work fine? I have other code that does this. What simple thing am I missing?
#include <map>
class MyRec {
public:
MyRec(int numberIn) : myNumber(numberIn) { };
int myNumber;
};
int main(int argc, char **argv)
{
typedef std::map<int, MyRec> Recs;
Recs recMap;
int num=104702;
int key=100923;
MyRec rec(num);
recMap[key] = rec; // Doesn't compile
// error: no matching function for call to MyRec::MyRec()
// samp.cpp:5: note: candidates are: MyRec::MyRec(int)
// samp.cpp:3: note: MyRec::MyRec(const MyRec&)
// Why do I receive the compile error for the above if it is the same as:
(*((recMap.insert(std::make_pair(key,rec))).first)).second;
recMap.insert(std::pair<int, MyRec>(key,rec)); // Works also of course
}

Consider this snippet:
std::map<int, Foo> map;
map[0];
This will actually work fine even if havent inserted an object for key 0. The reason is, that there is a difference between std::map::at() and std::map::operator []():
std::map::at() only returns a reference to an object inside the map. If there isnt an object for the given key, an exception is thrown.
std::map::operator []() does also return a reference, however if there no object for the given key, it creates an object inside the map and returns a reference to this newly created object. In order to create the object std::map must call the default constructor (a constructor with no additional arguments).
That is the reason why you code wont compile: Your class MyRec is not default constructable, but std::map::operator [] requires this.
Thus you have three options:
Use std::map::insert()
Use std::map::emplace()
Make MyRec default constructable.

In your code, you mention that you expect the [] operator to work the same as:
(*((recMap.insert(std::make_pair(key,rec))).first)).second;
But it is not the same as that statement; rather it's the same as:
(*((recMap.insert(std::make_pair(key,MyRec()))).first)).second;
Written like this, hopefully it's easier to see why the code doesn't compile (that is, MyRec does not define a parameter-less constructor).

Related

Calling a vector of function pointer

I am trying to use vector of function pointer in C++ which belongs to one class and being called in another class. For example: In class BoundaryCondition (file BoundaryCondition.h), I initialize the function pointer as:
class BoundaryConditions{
public:
// Constructor function
BoundaryConditions(int id = 0);
vector <void (BoundaryConditions::*) (Face &, int, int)> func2bcond;
void fixedValue(Face &face, int id, int rkStep);
// and other functions with similar definition as fixedValue
}
In another class (DG.h), I initialize an array of BoundaryCondition instance, something like
BoundaryCondition *bcond;
and assign memory to bcond variable using new (in file DG.cpp). For each bcond[i] instance, I need to assign memory to function pointer as:
this->bcond[i].func2bcond.resize(totNoOfVariable);
I am using resize instead of pushback as file reading may not be in the required order. Next, I am assigning function to this function pointer (again in DG.cpp) as per my boundary condition file:
bcond[i].func2bcond[j] = (&BoundaryConditions::fixedValue);
The code compiles alright till this point. I am getting error when I try to call these functions. I call this in DG.cpp. The code is as follows:
(bcond[i].*func2bond[j])(f,1,2);
I keep getting the following error:
error: 'func2bcond' was not declared in this scope
I am quite sure it is only matter of position of * or the brackets, but I am stuck here and I did not get any specific solved post on stackoverflow.
Thanks in advance
Pointer on method requires instance when called, so your code might look like:
(bcond[i].*(bcond[i].func2bond[j]))(f, 1, 2);
or, splitting expression:
auto methodPtr = bcond[i].func2bond[j]; // auto is `void (BoundaryConditions::*) (Face &, int, int)`
(bcond[i].*methodPtr)(f, 1, 2);

Using functions from classes

I am learning C++ and very new at using classes, and I am getting very confused in trying to use them. I am trying to convert my existing code (which used structs) so that it uses classes - so while I know what I am trying to do I don't know if I'm doing it correctly.
I was told that when using functions from the class, I first need to instantiate an object of the class. So what I have tried (a snippet) in my main function is:
int main()// line 1
{
string message_fr_client = "test"; //line2
msgInfo message_processed; //line 3
message_processed.incMsgClass(message_fr_client); //line 4
if (!message_processed.priority_check(qos_levels, message_processed)) //line 5
cout << "failure: priority level out of bounds\n"; //line 6
return 0; //line 7
}
Could you help me clarify if my following assumptions are correct? The compiler is not showing any error and so I don't know if it is error-free, or if there are ones lurking beneath.
At line 4, is the function incMsgClass being performed on the string message_fr_client and returning the resultant (and modified) message_processed?
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/*arguments*/)?
I haven't included the body of the functions because I know they work - I would just like to find out how the class functions interact. Please let me know if I can be clearer - just trying to clear up some confusion here.
Here is my class:
#ifndef clientMsgHandling_H
#define clientMsgHandling_H
#include <list>
#include <map>
#include <queue>
class msgInfo
{
public:
msgInfo();
msgInfo(int, int, int, std::string, std::list<int>);
/*classifying message*/
msgInfo incMsgClass(std::string original_msg);
/*message error checks*/
bool priority_check(int syst_priority, msgInfo msg); //check that message is within qos levels
bool route_check(std::map<std::pair<int, int>, int> route_table, msgInfo msg); //check that route exists
void getPath(msgInfo msg, std::map<std::pair<int, int>, int> route_info, int max_hop);
private:
int source_id;
int dest_id;
int priority;
std::string payload;
std::list<int> nodePath;
};
#endif
While it may compile (and even run), there are a few oddities with the code as shown:-
First off, class methods know which object they are operating on - so your priority_check and route_check methods probably don't need msgInfo as a parameter.,
for example, your old non-class function might be like this
bool priority_check(int p, msgInfo msg)
{
return msg.priority < p;
}
But the new one should look like this:
bool msgInfo::priority_check(int p)
{
return priority < p;
}
Also, incMsgClass is a bit odd, as it's a non-static class method that returns a msgInfo object. It's difficult to tell without understanding what it's supposed to do, but it seems possible that this function should actually be a constructor, rather than a regular method.
One other thing is that you're currently passing a msgInfo by value to those methods. So if the method needed to modify the passed msgInfo, it would not have any effect. It's generally better to pass objects by reference or const reference to other methods. So, back to the previous non-method example, it should really be this.
bool priority_check(int p, const msgInfo &msg)
...
But, as I said, you probably don't need the msgInfo parameters anyway.
At line 4, is the function incMsgClass being performed on the string message_fr_client
Yes
and returning the resultant (and modified) message_processed?
Whatever it's returning, you're ignoring the return value. It can modify the object itself, yes, because the function is not const.
At line 5, the function priority_check is being performed on the message_processed and returning a boolean?
Yes
In my class definition, I have a function getPath that is meant to modify the value of nodePath - is it just a matter of using message_processed.getPath(/arguments/)?
If a member function is intended to modify one of the class members, it's just a matter of not marking that function const
Hard to tell without implementation-details, but here we go:
I. You are passing a std::string as value (C++ is call-by-value by default), so you get a copy of the std::string in your method. If you want to work on the object you passed and manipulate it, use a reference on the object, like
msgInfo incMsgClass(std::string& original_msg); // notice the ampersand
then you can change your signature to
void incMsgClass(std::string& original_msg);
as you don't need to return the std::string you passed.
II. Yes, at least according to your signature
III. Can see a node_path only as a member.
For all your questions, see C++-FAQ.
Your basic assumptions are correct.
message_processed.incMsgClass(message_fr_client); //line 4
This line is not correct. The function you call returns msgInfo which is simply dropped. You should assign it to something. But it is not as it is usually done. You should make it a constructor of msgInfo, like
class msgInfo
{
public:
msgInfo(std::string original_msg);
...
}
Then you could call it like this
msgInfo message_processed(message_fr_client);
That line would create a msgInfo that is already properly initialized.
There is another pattern for creating class instances - static creating function. In your case you could mark incMsgClass static and then call it like
msgInfo message_processed = msgInfo.incMsgClass(message_fr_client);
I seriously doubt you need this pattern here, so I'd advise to move to constructor.
As of other functions, I see no problems there. Just note that all member functions not marked as const can modify the object they are called on. So, you don't need to pass this object explicitly. For functions a pointer to the object they are called on is available by name this. Also the functions can access all class variables as if these variables are global for normal (non-member) functions.

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);

C++ - Smart Pointers - Passing derived class shared pointer to base through template

I have the following and having difficulty resolving the error please help.
i have the following class as template definition somewhere.
template<class ConcreteHandlerType>
class SomeAcceptor: public ACE_Acceptor<ConcreteHandlerType, ACE_SOCK_Acceptor>
In some other file, i initialize this class in the constructor
class initialize {
typedef SomeAcceptor<BaseClassSomeHandler> baseAcceptor_t;
typedef SomeAcceptor<DerivedClassSomeHandler> derivedAcceptor_t;
boost::shared_ptr<baseAcceptor_t;> mAcceptor;
boost::shared_ptr<derivedAcceptor_t;> mDerivedAcceptor;
bool HandleAcceptNotification(BaseClassSomeHandler& someHandler);
initialize() : mAcceptor(0), mDerivedAcceptor(new DerivedAcceptor_t) {
mAcceptor->SetAcceptNotificationDelegate(fastdelegate::MakeDelegate(this, &initialize::HandleAcceptNotification));
}
}
Error i get is
error: no matching function for call to `boost::shared_ptr<SomeAcceptor<BaseClassSomeHandler> >::shared_ptr(int)'common/lib/boost_1_39_0/boost/smart_ptr/shared_ptr.hpp:160: note: candidates are: boost::shared_ptr<SomeAcceptor<BaseClassSomeHandler> >::shared_ptr(const boost::shared_ptr<SomeAcceptor<BaseClassSomeHandler> >&)
common/lib/boost_1_39_0/boost/smart_ptr/shared_ptr.hpp:173: notboost::shared_ptr<T>::shared_ptr() [with T = SomeAcceptor<BaseClassSomeHandler>]
I also tried overloading the function with
bool HandleAcceptNotification(DerivedClassSomeHandler& someHandler);
but because mAcceptor is of type SomeAcceptor BaseClassSomeHandler, i get this error, but to fix this.
I guess i need to cast it somehow, but how to do it?
i tried doing like below inside the constructor and it didn't work
initialize() : mAcceptor(0), mDerivedAcceptor(new DerivedAcceptor_t) {
mAcceptor = mDerivedAcceptor; // Error here
mAcceptor->SetAcceptNotificationDelegate(fastdelegate::MakeDelegate(this, &initialize::HandleAcceptNotification));
}
From your code, it looks like you want mAcceptor to be assigned NULL (0), if that is the case you don't need to initialize it at all, as the default constructor will take care of that. But, since you call a function on that (NULL) pointer immediately, its not immediately clear exactly what you want to do.
If you want mAcceptor and mDerivedAcceptor to point to the same (shared) object and assuming DerivedClassSomeHandler is derived from BaseClassSomeHandler, this is a situation where you should use boost::shared_static_cast, as described here.
There's also some good information in this apparently related question.
The error is due to the mAcceptor(0) in
initialize() : mAcceptor(0), mDerivedAcceptor(new DerivedAcceptor_t) {
mAcceptor->SetAcceptNotificationDelegate(fastdelegate::MakeDelegate(this, &initialize::HandleAcceptNotification));
}
The smart_ptr default constructor assigns the wrapped ptr to NULL, so leave out mAcceptor(0) from the initialization list.
boost::shared_ptr<SomeAcceptor<BaseClassSomeHandler> >::shared_ptr(int)
It's yelling at you that there's no constructor that accepts an int.
Just use: mAcceptor()

C++ boost function issue

I did something to break the functionality in my program, but I can't figure out what. I define a typedef in a class headerfile:
typedef boost::function<void(instr_ptr, std::vector<ResultBase*>) > GenFunction;
And inside that class I have two instances:
GenFunction Gen;
GenFunction Kill
I set them as follows:
void DataFlowSolver::SetGenFunction(GenFunction &func)
{
Gen = func;
}
void DataFlowSolver::SetKillFunction(GenFunction &func)
{
Kill = func;
}
I have another function in a seperate header file:
void GenLiveVar(const instr_ptr instr, std::vector<ResultBase*> &list);
I create an instance of the DataFlowSolver class, and attempt to assign into it as follows:
blockSolver.SetGenFunction(GenLiveVar);
However, the compiler complains:
CFG.cc:617: error: no matching function for call to
'DataFlowSolver::SetGenFunction(void (&)(instr_ptr,
std::vector >&))'
DataFlowSolver.h:21: note: candidates are: void
DataFlowSolver::SetGenFunction(GenFunction&)
But it lets me do this:
GenFunction fun = GenLiveVar;
blockSolver.SetGenFunction(fun);
Anyone have an idea what might be wrong? I know this worked before, but I'm not sure how I managed to break it...
You are passing the boost::function into Set*Function by non-const reference. That prevents temporaries from being used as arguments, and the conversion from a normal function to a boost::function creates a temporary value. You will need to use a const reference for your parameter type for the code to work correctly.