Getting information out of a set<MyClass> mySet - c++

So I've got
set<MyClass> mySet;
and in MyClass I have a static int to count the number of compares that happen. I'm trying to get that information out of it but I can't figure out how.
This is what I've tried:
set<MyClass>::iterator it = mySet.begin();
int count = it->getCompareCount();
and
int count = mySet.begin()->getCompareCount();
Neither of those work (Yes I know the are essentially the same exact thing) but I can get that information out of something that is indexed like a std::list or std::vector
Example:
vector<MyClass> myVector;
for (int i = 0; i < 10; i ++)
{
myVector.push_back(MyClass(i,"Some Name", i*2);
}
int count = myVector.at(2).getCompareCount(); //which by default is going to be 0 as no compares have taken place
Can anybody help me? netbeans says "error: passing ‘const MyClass’ as ‘this’ argument of ‘int MyClass::getCompareCount()’ discards qualifiers [-fpermissive]" when I do what I said I tried up above.
EDITS
Declaration of getCompareCount():
int MyClass::getCompareCount()
{
return compareCount;
}

Element in std::set is not mutable after it is inserted into the set. When you dereference an iterator (as in it->), it returns a const reference of the object you put into the set. On the other hand, your definition of getCompareCount() is a non-const instance function meaning it can only be called on non-const instance of the class. Define the function as the following should solve your problem.
int MyClass::getCompareCount() const
{
return compareCount;
}
By the way, since compareCount is a static int, you might want to define the function as static as well so that you can call it using the class instead of having to get an instance to call it.
static int MyClass::getCompareCount()
{
return compareCount;
}
//To Call it
MyClass::getCompareCount()

Related

c++ "error:passing 'const std::vector<int>' as 'this' argument discards qualifiers [-fpermissive]"

I am trying to implement this POMDP solver with given examples for my decision making problem and I followed the documentation in the repository to build different relevant classes and functions in the header file
class SimpleState: public State {
public:
int position;
int context;
int time;
SimpleState();
SimpleState(int _position, int _context, int _time) :
rat_position(_position),
context(_context),
time(_time) {
}
SimpleState(int _state_id);
~SimpleState();
std::string text() const;
};
SimpleState::SimpleState() {
}
class StarMazeProblem : public DSPOMDP,
public MDP {
protected:
std::vector<std::vector<std::vector<State> > > transition_probabilities_; //state, action, [state, weight]
mutable MemoryPool<SimpleState> memory_pool_;
std::vector<SimpleState*> states_;
mutable std::vector<ValuedAction> mdp_policy_;
public:
enum {CENTER = 0, RIGHT = 1, LEFT = 2};
public:
StarMazeProblem();
int NumStates() const;
void ComputeDefaultActions(std::string type) const;
ParticleUpperBound* CreateParticleUpperBound(std::string name = "DEFAULT") const;//?
ScenarioUpperBound* CreateScenarioUpperBound(std::string name = "DEFAULT",
std::string particle_bound_name = "DEFAULT") const;
ScenarioLowerBound* CreateScenarioLowerBound(std::string name = "DEFAULT",
std::string particle_bound_name = "DEFAULT") const;
}
and in the starmaze.cpp file the relevant lines are
int StarMazeProblem::NumStates() const {
return CONTEXT * POSITIONS * TIME;
}
void StarMazeProblem::ComputeDefaultActions(string type) const {
cerr << "Default action = " << type << endl;
if (type == "MDP") {
const_cast<StarMazeProblem*>(this)->ComputeOptimalPolicyUsingVI();
int num_states = NumStates();
default_action_.resize(num_states);
double value = 0;
for (int s = 0; s < num_states; s++) {
default_action_[s] = policy_[s].action;
value += policy_[s].value;
}
} else {
cerr << "Unsupported default action type " << type << endl;
exit(0);
}
}
ScenarioLowerBound* StarMazeProblem::CreateScenarioLowerBound(string name,
string particle_bound_name="DEFAULT") const {
const DSPOMDP* model = this;
const StateIndexer* indexer = this;
const StatePolicy* policy = this;
ScenarioLowerBound* bound = NULL;
if (name == "TRIVIAL" ) {
bound = new TrivialParticleLowerBound(this);
} else if (name == "RANDOM") {
bound = new RandomPolicy(this,
CreateParticleLowerBound(particle_bound_name));
} else if (name == "MODE" || name == "DEFAULT") {
ComputeDefaultActions("MDP");
bound = new ModeStatePolicy(model, *indexer, *policy,
CreateParticleLowerBound(particle_bound_name));
} else {
cerr << "Unsupported scenario lower bound: " << name << endl;
exit(1);
}
return bound;
}
here I got the following error for the above code:
src/starmaze.cpp:301:36: error: passing 'const std::vector<int>' as 'this' argument discards qualifiers [-fpermissive]
default_action_.resize(num_states);
^
In file included from /opt/local/include/gcc7/c++/vector:64:0,
from ../../../include/despot/interface/lower_bound.h:4,
from ../../../include/despot/core/builtin_lower_bounds.h:4,
from src/starmaze.h:3,
from src/starmaze.cpp:1:
/opt/local/include/gcc7/c++/bits/stl_vector.h:689:7: note: in call to 'void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type) [with _Tp = int; _Alloc = std::allocator<int>; std::vector<_Tp, _Alloc>::size_type = long unsigned int]'
resize(size_type __new_size)
^~~~~~
I have basic c++ knowledge and I could not figure out the reason for the error since I followed the examples. Any suggestion?
Important to know before reading
I've looked over this code several times, and cannot find where default_action_ is declared as a const std::vector<int>. This leads me to assume (based on the fact that the compiler recognizes it as such) that the variable is declared in one of the parent classes: public DSPOMDP, public MDP.
You are trying to modify a const vector<int>
This issue is pretty straight-forward.
You cannot change a const std::vector<Ty>
The whole point of making something const is to prevent the programmer from changing it.
Whatever you are trying to do here, you should consider copying the vector data into a new vector, and make the changes to it in the copy.
Okay so let's say you decided to do the naughty deed and remove const from the *.h file wherever it may be. You'll still have an issue (see below)
You are trying to modify the class instance from a const method
This is if you removed const from the vector
The default_action_.resize(num_states); is going to cause the compiler to yell at you.
The issue here is now your method StarMazeProblem::ComputeDefaultActions() is specified as const. This means you cannot change your class instance in any way from within that function/class method. What you are doing is modifying the default_action_ vector by calling resize() on it. This inevitably changes the class instance which is forbidden because your method is declared const and your default_action_ vector is declared somewhere in your class hierarchy. Additionally you are changing the vector directly by assigning it to an rvalue (See code below)
int num_states = NumStates();
default_action_.resize(num_states); // <---- default_action_ cannot be modified
for (int s = 0; s < num_states; s++) {
default_action_[s] = policy_[s].action; // <---- default_action_ cannot be modified
value += policy_[s].value;
}
Solution
You need a copy of the vector you are trying to modify. Going into h files and changing them without knowing 100% exactly what you are doing is never the answer.
Making a temporary vector in the class method, copying the data to it, and manipulating the copy is completely allowed and will not give you any compiler errors; however, this approach may completely avoid your official goal. It looks like you are really trying to change the default_action_ vector and that almost seems like your true goal here.
It's hard for me to give you a definitive answer on this specific topic. Mainly because I do not know what this entire class hierarchy does or what it is for exactly (I briefly looked over the code in the link provided.)
What you'll need to do ultimately is determine why you are trying to change that vector, and why it was made const by the original developers. Then you can determine if there is a better way other than explicitly removing the constness of the vector.
If you are still trying to make changes to the class instance read below
This solution part has to do with the qualifier of the class you are dealing with.
You can either remove the constant qualifier from the class method if it is absolutely necessary to make changes to the class instance from within that method.
OR
Find an alternative method for what you are trying to do, and break it up into multiple method calls on the class instance.
You've made ComputeDefaultActions() const-qualified, but there is very little that says that it should be.
It calls ComputeOptimalPolicyUsingVI() which is not const-qualified since it changes the internal state of *this. You've worked around that by casting away const on this - but that function resizes policy_ to also be NumStates() big which ComputeDefaultActions() depends on - otherwise the internal loop would be very dangerous.
It changes default_action_ by resizeing it and by assigning its elements. This may be a mistake, if the computation made is actually meant to not change *this but ... (see next bullet)
It doesn't return anything. Everything the function does is to change the internal state of *this. The computed value is just dropped at the end of the calculation and it's not even used internally in the function. Either make the function return value or remove value completely.
Suggested changes:
#include <algorithm>
#include <stdexcept>
void StarMazeProblem::ComputeDefaultActions(string type) { // non-const
cerr << "Default action = " << type << endl;
if (type == "MDP") {
ComputeOptimalPolicyUsingVI(); // no casting needed
default_action_.resize(policy_.size()); // dependency made clear
// Use the standard transform function:
std::transform(policy_.begin(), policy_.end(), default_action_.begin(),
[](const auto& p) { return p.action; });
} else {
// friendlier than exit():
throw std::runtime_error("Unsupported default action type " + type);
}
}

Node-Addon-Api Pass Array As Function Argument

I am trying to create a basic native node addon where a javascript array is passed from node and then processed in c++. The problem is I cannot figure out how to correctly pass the array. I can instantiate the array without issue but assigning it using info[0].as throws errors.
My c++ code is
#include <napi.h>
using namespace Napi;
using namespace std;
Value Add(const CallbackInfo& info)
{
Env env = info.Env();
Array result = Napi::Array::New(env);
Array a = info[0].As<Array>;
double arg1 = info[1].As<Number>().DoubleValue();
Number num = Napi::Number::New(env, 2 + arg1);
return num;
}
The error I am getting is
../cppsrc/main.cpp: In function ‘Napi::Value Add(const Napi::CallbackInfo&)’:
../cppsrc/main.cpp:12:21: error: conversion from ‘<unresolved overloaded function type>’ to non-scalar type ‘Napi::Array’ requested
Array a = info[0].As<Array>;
~~~~~~~~^~~~~~~~~
What is the correct way to pass an array to c++? Is it even possible?
This works for me:
void runSetPropertyAsyncWorker(const CallbackInfo& info)
{
std::string path = info[0].As<Napi::String>();
int property = info[1].As<Number>();
int dataSize = info[2].As<Number>();
Array b = info[3].As<Array>();
for(int i = 0; i<b.Length(); i++)
{
Napi::Value v = b[i];
if (v.IsNumber())
{
int value = (int)v.As<Napi::Number>();
...
...
}
}
...
...
Function callback = info[4].As<Function>();
AsyncWorker* asyncWorker = new SetPropertyAsyncWorker(callback, ...);
asyncWorker->Queue();
}
Use Napi::Object. Napi::Array is actually inherited from Napi::Object.
You could replace the code Array a = info[0].As<Array>; with Array a = info[0].ToObject();.
You can then access the data members via Value
operator[] (uint32_t index) const
Source: https://nodejs.github.io/node-addon-api/class_napi_1_1_object.html
Edit: Bonus feature, if an argument that is not an object is passed, this will automatically trigger an Error: Object Expected.
error code here:
Array a = info[0].As<Array>;
which should be
Array a = info[0].As<Array>();
I was not able to find a solution to the actual question of interacting with the Javascript object directly with node-addon-api. The Solution that I chose to go with is JSON.stringify any arrays or objects and then parse then in c++ is a library called rapid json. This proves to be the only way to interface with javascript objects that i've been able to find

c++ save class templated function pointer inside map

I'm having a small problem which I can't wrap my head around.
I have a function that looks like this:
template <typename T>
std::unique_ptr<Environment>& CreateEnvironment(sf::Vector2f& _position, bool _addToStatic = false);
This is my function pointer typedef
typedef std::unique_ptr<Environment>& (WorldEditor::*CreateEnvironmentPtr)(sf::Vector2f&, bool);
std::map<std::string,CreateEnvironmentPtr> listEnv;
And I'm trying to simply do this:
listEnv["test"] = &CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
And i get the following error:
error C2440: '=' : cannot convert from 'std::unique_ptr<_Ty> *' to
'std::unique_ptr<_Ty> &(__thiscall WorldEditor::* )(sf::Vector2f
&,bool)'
I understand what the error is saying, but I don't know how to solve it. Also why does it even care about the return type when I'm pointing to the address of the function?
Best regards
nilo
problems such as these are often much better solved with std::function
std::map<std::string, std::function<void()> listEnv;
listEnv.emplace("test", [] {
CreateEnvironment<Coin>(sf::Vector2f(200,200), false);
});
to call:
listEnv.at("test")->second();
Based on your post I am not sure if you are attempting to create the member function pointer and map inside the CreateEnvironment class or outside of it, so I'll solve what I think is the more difficult problem of pointer to a separate object's member function.
I simplified your classes like so:
Environment
struct Environment
{
int i = 1;
};
Coin
struct Coin
{
int k = 0;
};
WorldEditor
struct WorldEditor
{
template <typename T>
std::unique_ptr<Environment> CreateEnvironment(int& _j, bool _addToStatic = false)
{
return std::make_unique<Environment>();
}
};
Solution: Map an object's member fn pointer, and then call it later
(I will be using C++11/14 syntax in my answer)
//declare a pointer to member function in WorldEditor
using CreateEnvironmentPtr = std::unique_ptr<Environment> (WorldEditor::*)(int&, bool);
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to the CreateEnvironment<Coin> function
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = &WorldEditor::CreateEnvironment<Coin>;
// call the member function pointer using the instance I created, as well as
// the mapped function
(myWorldEditor.*listEnv["test"])(myInt, false);
// (printing member value to cout to show it worked)
std::cout << (myWorldEditor.*listEnv["test"])(myInt, false)->i << std::endl; // prints 1
Live Demo
Solution 2: use std::bind and std::function
Perhaps we already know the parameters to the member function call at the time we create the entry for map. Using std::bind with a std::function will help us achieve that (Similar to Richard Hodges' solution):
// now our "function pointer" is really just a std::function that takes no arguments
using CreateEnvironmentPtr = std::function<std::unique_ptr<Environment>(void)>;
//declare an object of type WorldEditor, because member function pointers need a "this" pointer
WorldEditor myWorldEditor;
int myInt = 42;
//map a string to that function pointer
//ensure it gets called with the right args
// by using std::bind (which will also make the arg list appear the be void at call time)
// note that std::bind needs an instance of the class immediately after
// listing the function it should be binding
// only afterwards will we then pass the int& and bool
std::map<std::string, CreateEnvironmentPtr> listEnv;
listEnv["test"] = std::bind(&WorldEditor::CreateEnvironment<Coin>, &myWorldEditor, myInt, false);
// the mapped function
listEnv["test"]()->i;
// (printing resulting unique_ptr<Environment>'s member to cout to show it worked)
std::cout << listEnv["test"]()->i << std::endl; // prints 1
Live Demo 2

Calling a function on the this keyword

So in my header file I have these two variables declared as private
private:
char* data;
int len;
and give this to access it
int length() const { return len; }
Then in my cpp file I am trying to override the operators in string implementation like this:
bool MyString::operator>(const MyString& string)
{
//Compare the lengths of each string
if((this.length()) > (string.length())){
return 0;
}
//The given string is shorter
return -1;
}
when I compile this I get this error:
mystring.cpp:263:14: error: request for member ‘length’ in ‘this’, which is of non-class type ‘MyString* const’
From what I can tell by trying to call the .length() on the this is trying to access a variable on the this pointer which is causing a problem, like in this question.
That's fine because I can do this instead:
bool MyString::operator>(const MyString& string)
{
//Compare the lengths of each string
if((this->len) > (string.length())){
return 0;
}
//The given string is shorter
return -1;
}
which compiles fine but now I'm wondering how do you call a function on a this pointer. I thought that because it was a pointer I would have to dereference it first so I tried this:
bool MyString::operator>=(const MyString& string)
{
//Compare the lengths of each string
if((*(this).length()) >= (string.length())){
return 0;
}
//The given string is shorter but not equal
return -1;
}
But again I got this error:
mystring.cpp:273:17: error: request for member ‘length’ in ‘this’, which is of non-class type ‘MyString* const’
It seems like this should have worked fine as I would have dereferenced the pointer into the object it pointed to which does indeed have that method but I seem to be missing something. How would I go about calling a function defined in my class on the this pointer? And is there some functional reason why the way I described above does not work?
if((this.length()) > (string.length())){
This should be
if((this->length()) > (string.length())){
as this is a pointer.Basically this is just a pointer referring to the object on which member function is called. So, you have to use -> for all reference to members of that class.
One more advice stop using variable names which are standard keywords. like string in your case. Had you included std namespace you would have got the reason for not doing so.

return an array of void*

I am building a C++ program that needs to store a map of strings to function pointers. However, every function may have different return types and parameters. The way I am attempting to solve this problem is by creating the functions as taking an array of void pointers and returning an array of void pointers, and then casting the arguments and return values as needed.
To figure out how this would work, I'm trying to build a simple dummy, but can't get it to compile. I've tried a number of things, but I keep getting different errors. here's an example:
#include <string>
#include <iostream>
#include <map>
using namespace std;
void** string2map(void** args){
//takes a string of the form "key:value;key:value;..." and returns a map<string,string>
string st = *((string**) args)[0];
map<string, string> result = map <string, string>();
//code doesnt matter
return (void*) &((void*) &result);
}
int main(){
string test = "hello:there;how:are you?";
map<string, string> result = *(map<string, string>**)string2map((void*) &((void*) &test))[0];
return 0;
}
when I try to compile, I get:
void.cpp: In function 'void** string2map(void**)':
void.cpp:12:34: error: lvalue required as unary '&' operand
void.cpp: In function 'int main()':
void.cpp:17:89: error: lvalue required as unary '&' operand
Obviously there are plenty of things wrong here, but I really just don't know where to start. Can anyone either show me what's wrong with the code above, or give me an alternative to the way I am currently doing it?
NOTE
The reason I am returning a void** instead of just void* is that there might be a circumstance where I need to return multiple values of different types. An example would be if, above, I wanted to return both the resulting map AND the number of entries in the map. I haven't even gotten to the point of figuring out how to construct that array yet, though.
EDIT
So based on the responses so far, it seems pretty clear that this is the wrong way of solving this problem. With that in mind, can anyone suggest a better one? I need to be able to store the various function in a single map, which means I need to be able to define a single data type to functions that take and return different types. And it IS important to be able to return multiple values.
You're converting a map<string,string> to a void**, returning it then converting it back to a map<string,string. Why not just return a map<string,string>? It's also called string2map which implies you will only ever call it with a string (backed up by the fact you pass in a string, which is converted to a void** then converted straight back). Unless you have a good reason to convert to and from void** all over the place this is probably what you need:
#include <string>
#include <iostream>
#include <map>
using namespace std;
map<string, string> string2map(string st){
map<string, string> result = map <string, string>();
//code doesnt matter
return result;
}
int main(){
string test = "hello:there;how:are you?";
map<string, string> result = string2map(test);
return 0;
}
EDIT:
I've just reread your question. You might want to look up Generalised Functors and look at Boost's std::function as possible solutions to this problem. It's possible to change the return type of a function via a wrapper class, something like:
template< class T >
class ReturnVoid
{
public:
ReturnVoid( T (*functor)() ) : m_functor( functor ) {}
void operator() { Result = functor(); }
private:
T (*m_functor)();
T Result;
};
// Specialise for void since you can't have a member of type 'void'
template<>
ReturnVoid< void >
{
public:
ReturnVoid( T (*functor)() ) : m_functor( functor ) {}
void operator() { functor(); }
private:
T (*m_functor)();
};
Using this as a wrapper might help you store functors with different return types in the same array.
Ignoring my own horror at the idea of blatantly throwing type safety to the wind, two things spring immediately to mind.
First, what exactly do you think will be pointed to when string2map goes out of scope?
Second is that you don't have to cast to void*. Void* gets special treatment in C++ in that anything can be cast to it.
If you insist on trying to push this, I'd start by changing the return type to void, and then take the void* as an input parameter to your function.
For example:
void string2map(void* args, void* returnedMap);
This way you'd have to instantiate your map in a scope that will actually have a map to point to.
$5.3.1/3 - "The result of the unary & operator is a pointer to its
operand. The operand shall be an lvalue or a qualifiedid."
$5.3.1/2 - "The result of each of the following unary operators is a
prvalue."
So, in effect you are trying to take the address of an rvalue which is not allowed.
Further, C++ does not allow to return an array.
So, you really want to start looking at what you want. Return the map by value instead is one definite option.
The way I am attempting to solve this problem is by creating the functions as taking an array of void pointers and returning an array of void pointers, and then casting the arguments and return values as needed.
That's (really really) bad. Have a look instead at std::function and std::bind - those should cover differences between function signatures and bound arguments in an elegant way.
The reason I am returning a void** instead of just void* is that there might be a circumstance where I need to return multiple values of different types.
Then return an object that contains the values. For generics have a look at std::tuple or boost::any.
Here's some code:
void function1(int, const char); // defined elsewhere
std::tuple<int,int> function2(std::string&); // defined elsewhere
std::map<std::string,std::function<void(void)>> functionmap;
functionmap.insert( std::make_pair("function1", std::bind(&function1, 2, 'c')) );
std::tuple<int,int> result;
functionmap.insert( std::make_pair("function2", [&result] {
result = function2("this is a test"); } );
// call function1
functionmap["function1"]();
// call function2
functionmap["function2"](); // result will now contain the result
// of calling function2
Is this what you tried to do?
int Foo(int a) { return a; }
typedef int (*FooFunc)(int);
void Bar(){}
typedef std::map<std::string, void*> FunctionMap;
// you should use boost::any or something similar instead of void* here
FunctionMap CreateFunctionMap(const std::string& args)
{
FunctionMap result;
result["Foo"] = &Foo;
result["Bar"] = &Bar;
return result;
}
void Call(FunctionMap::const_reference functionInfo)
{
// #hansmaad The key will give information on the signatures.
// there are a few distinct options, so it will be a conditional
// with a couple of clauses.
if (functionInfo.first == "Foo")
{
auto f = static_cast<FooFunc>(functionInfo.second);
std::cout << f(42);
}
else if (functionInfo.first == "Bar")
{
/* */
}
}
int main()
{
auto functions = CreateFunctionMap("...");
std::for_each(begin(functions), end(functions), Call);
}
#hansmaad The key will give information on the signatures. there are a few distinct options, so it will be a conditional with a couple of clauses. – ewok 33 mins ago
In that case, the typical solution is like this:
typedef void (*func_ptr)();
std::map<std::string, func_ptr> func_map;
map<string,string> string2map(string arg){
//takes a string of the form "key:value;key:value;..." and returns a map<string,string>
map<string, string> result = map <string, string>();
//...
return result;
}
// ...
// Add function to the map
func_map["map<string,string>(string)" = (func_ptr)string2map;
// Call function in the map
std::map<std::string, func_ptr>::iterator it = ...
if (it->first == "map<string,string>(string)")
{
map<string,string> (*func)(string) = (map<string,string>(*)(string))it->second;
map<string,string> result = func("key1;value1;key2;value2");
}
For brevity, I have used C-style casts of the function pointers. The correct C++ cast would be reinterpret_cast<>().
The function pointers are converted to a common type on insertion into the map and converted back to their correct type when invoking them.