Passing vector iterator to a function c++ - c++

Can anyone explain to me why the following segment compiles but the commented line after doesn't?
struct tObj
{
int data;
int moreData;
}
...
void funcToCall (tObj *obj, int moreData)
{
//Useful stuff here
}
void mainFunction ()
{
vector<tObj>::iterator it = vectorOfObjects.begin(); //assumes vectorOfObjects is already defined
while (it != vectorOfObjects.end())
{
funcToCall (&(*it), 0); //This line works
funcToCall (it, 0); //This line produces an error
it++;
}
}
The error produced is this:
error: cannot convert ‘std::vector<tObj>::iterator {aka __gnu_cxx::__normal_iterator<tObj*, std::vector<tObj> >}’ to ‘tObj*’
Any ideas on why &(*it) works but just plain it doesn't? Logically they are the same, aren't they?
Because doesn't * mean to dereference and & mean pass by reference aka cancelling each other out?

it is an iterator object, passing it as-is would mean you're trying to pass an object of type vector<tObj>::iterator for a function expecting tObj*, and thus the error.
When you do *it you'd get the underlying object the iterator is representing and when you apply & atop that, you get that object's address, which is of type tObj* which agrees with the function's argument type and thus no error.

That the code would be compiled you have to declare an overloaded function like
void funcToCall ( std::vector<tObj>::iterator it, int moreData)
{
//Useful stuff here
}
In general case types tObj * and vector<tObj>::iterator are different types though in some old realizations of std::vector its iterator is indeed defined as a pointer..

Related

Passing an object pointed to by an iterator by reference to a function C++

I though that I understood iterators and addressing etc. but obviously not. See my below code below which is purely an example.
I need to be able to pass by pointer or reference each structure of mystructs to MyFunc(). The function should be able to update the actual structure that is passed, and not by copy or value.
I receive the compiler error :
error: cannot convert 'MY_STRUCT' to 'MY_STRUCT*' for argument '1' to 'void MyFunc(MY_STRUCT*)'
If I just pass the iterator address, this also doesn't work.
What is the correct way to do this. Thanks in advance.
typedef struct
{
int var1;
int var2;
std::string name;
}MY_STRUCT;
std::list<MY_STRUCT> mystructs;
void MyFunc(MY_STRUCT*)
{
// Do something
}
// populate the list with structs etc.. not included here
//.....
for (std::list<MY_STRUCT>::iterator it = mystructs.begin();it != mystructs.end(); ++it)
{
MyFunc(*it);
}
Passing by reference in C++ is done with:
void MyFunc(MY_STRUCT&)
{
// Do something
}
So your call would be correct, what you currently want is to pass the pointer, which you can do with dereferencing the dereferenced iterator (by passing the address of the dereferenced object):
void MyFunc(MY_STRUCT*)
{
// Do something
}
// populate the list with structs etc.. not included here
//.....
int main() {
for (std::list<MY_STRUCT>::iterator it = mystructs.begin();it != mystructs.begin(); ++it)
{
MyFunc(&*it);
}
}
Your function requires a pointer, use & to get the address of something.
MyFunc(&*it);
*it returns a reference to the MY_STRUCT object, you need to use & to convert that reference to a pointer. This is normal, the fact that you are using iterators makes no difference at all.
The alternative (maybe better in C++) would be to convert your MyFunc function to take a reference instead of a pointer.

ESP was not properly saved across a function call when using function pointers

I am trying to create a program which saves the function pointer of a member function to an array. The program then takes the function pointer from that array and calls the function said pointer points to. This works as long as the member function used does not have any arguments. When I give it arguments the following error occurs in Visual Studio 2017:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
My code is:
typedef uint8_t byte;
template<typename T>
class Test
{
public:
void FuncTest(byte* data)
{
cout << (T)(0.0625f) << endl;
}
};
typedef Test<float> fTest;
typedef Test<long long> lTest;
int main()
{
byte data[1024];
{
void (fTest::*ffp)(byte*) = &fTest::FuncTest;
//void (lTest::*lfp)(byte*) = &lTest::FuncTest;
printf("%p\n", ffp);
memcpy(&data[0], (int64*)&ffp, sizeof(int64));
}
{
int64 pData;
memcpy(&pData, &data[0], sizeof(int64));
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
printf("%p\n", pData);
func_pointer(nullptr);
}
}
If anyone could help, it would be greatly appreciated.
Ignoring the storage in an array your code is essentially:
void (Test::*ffp)(byte*) = &fTest::FuncTest;
void* pData = (void*)ffp;
void(*func_pointer)(byte*) = (void(*) (byte*))(pData);
func_pointer(nullptr);
The type of ffp is essentially (although not exactly due to differing calling conventions) void (fTest*, byte*) which doesn't match the type of func_pointer.
The solution to this is to use std::function with with either std::bind or lambdas to convert the function signatures. e.g.:
std::vector<std::function<void(byte*)>> functions;
fTest test;
functions.push_back([=](byte* data){ test.FuncTest(data); });
functions.front()(nullptr);

Passing map<>::iterator as map<>::const_iterator &

I have a problem passing a map<...>::iterator object to a function as a const_iterator & on GCC:
class MyClass {
};
bool MyClass::_GetInstList(map<string,InstList>::const_iterator & it, const string & sMod)
{
cout<<"Matched\n";
it = tInstancesData.find(sMod);
if( it == tInstancesData.end() ) {
cout<<"\""<<sMod<<"\" is NOT a module\n";
return false;
}
return true;
}
bool SomeFunction()
{
map<string,InstList>::iterator it;
if( ! _GetInstList(it, SomeString) ) return false;
it->second.Add(...); // Modifying element pointed by "it"
}
My probelm is that on Visual Studio 2010 the code above works perfectly fine, but on GCC 4.1.2 I get an error saying there is no matching function to the function call, for _GetInstList(it, SomeString). The issue seems to be converting iterator to const_iterator &.
I have to take it by reference because "it" gets changed inside _GetInstList() and the caller function checks it. (The "it" pointer is changed not a pointed element).
Also, the "it" in SomeFunction() cannot be const because it changes an element.
How can I resolve this?
EDIT:
For those who suggest that the problem is the conversion from iterator to const_iterator:
The code compiles fine if the function prototype is changed to take const_iterator NOT as a reference, the problem is the const &.
Change your argument type to const map<string,InstList>::const_iterator& or just a map<string,InstList>::const_iterator.
Here's an example demonstrating your problem (and the solution) with simple types:
void func1(double& x){}
void func2(const double& x){}
int main()
{
int x;
func1(x); // error: 'func1' : cannot convert parameter 1 from 'int' to 'double &'
func2(x); // succeeds
}
I think maybe this method should be redesigned anyway. Passing iterators around is messy and confusing for others to read. How hard would it be to do that?

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.

Casting void *user_data to object

how do I cast void *something to an object in standard C++?
Specifically I want want to cast void *userdata
to std::map<String, void*>
Is this possible? I am trying:
//void *user_data is a parameter of this function (callback)
std::map <String, void*> user_data_n; //this line is ok
user_data_n = static_cast<std::map<String, void *>>(*user_data); //I get the errors here.
ERRORs:
Spurious '>>' user '>' to terminate a template argument list
Expected '>' before '(' token
'void *' is not a pointer-to-object type
or is there a better way to carry information about the caller object and some other parameters I can pass to void *user_data?
UPDATE:
Ass suggested by #aaa carp I changed >> to > > and the first two errors were solved. The last is strange, Why do I get that kind of message when casting it here and not when putting that object when setting the callback?
std::map<String, void*> user_data_h;
user_data_h["Object"] = this; //this is a MainController object
user_data_h["h"] = h; //h was defined as int *h
createTrackbar("trackbar_H", winName, h, 255, trackbar_handler, &user_data_h);
where createTrackbar is defined as:
int createTrackbar( const string& trackbarname, const string& winname,
int* value, int count, TrackbarCallback onChange, void* userdata);
UPDATE2:
doing this solved my problem but following the same approach, why I still get error when trying to cast objects contained in my map object?
void trackbar_handler(int value, void *user_data){
std::map <String, void*> *user_data_map;
user_data_map = reinterpret_cast<std::map<String, void *> *>(user_data); //WORKED!! ;)
MainController *controller; //the same class type I put using "this" above
controller = reinterpret_cast<MainController *>( user_data_map["Object"]); //ERROR here
int *var = reinterpret_cast<int*> (user_data_map["h"]); //ERROR also here
>> should be > >
and you do not want to dereference void pointer, instead cast void pointer to desired pointer type and then dereference
#casa has already provided you with answer to second problem
When you're casting from a void *, your result will be a pointer too. So the map declaration should be:
std::map <String, void*> *user_data_n;
Second, you should use reinterpret_cast for such (potentially dangerous) casts:
user_data_n = reinterpret_cast<std::map<String, void *> *>(user_data);
Update:
As others suggested, you could simply use a static_cast as well.
Why do I get that kind of message when casting it here and not when putting that object when setting the callback?
Any pointer can be implicitly converted to void *, but when converting it back to a pointer of some specific type, you need an explicit cast.
why I still get error when trying to cast objects contained in my map object?
As already mentioned in the comments, you need to dereference the pointer before using the map object. You might want to define a reference instead to make things easier:
std::map <String, void*> &user_data_map =
*(static_cast<std::map<String, void *> *>(user_data));
An noted, the >> in that line to close your template should be > > (with a space).
Also, if user_data is a void pointer, you cannot dereference it. You could cast the pointer to another pointer type with reinterpret_cast:
std::map <String, void*> *user_data_n_ptr; //note this is a pointer to a map.
user_data_n_ptr = reinterpret_cast<std::map<String, void *> *>(user_data);
This will cast the void pointer to a std::map .
You should be careful with this. void pointers shouldn't typically be thrown around in c++. There may be a better way to do what you want and avoid void * all together.
I suppose this is for serving a C callback? It might be better to have a specialized struct which keeps all those values using the exact types. That way you'd be down to one cast for the whole thing. Something like this:
struct callback_user_data {
my_class* that;
int number;
callback_user_data(my_class* p, int i) : that(p), number(i) {}
};
// the callback
void my_callback(void* user_data)
{
callback_user_data* cbud = static_cast<callback_user_data*>(user_data);
somehow_use(cbud->that, cbud->number);
}
//call the function, passing our user data
callback_user_data cbud(this, 42);
some_function_taking_our_callback(&my_callback, &cbud);
Note that usually I have this seen (and used) this so that not a special type is passed, but only this, which has all the necessary data anyway:
// the callback
void my_callback(void* user_data)
{
my_class* that = static_cast<my_class*>(user_data);
that->f();
std::cout << that->number << '\n';
}
//call the function, passing our user data
some_function_taking_our_callback(&my_callback, this);