std::map, storing pointer (to object) by pointer (to some object's related struct). Which types to use?
To overcome the impossibility of giving C library a callback to C++ member function, wanted to implement something like this:
SomeObject* findSomeObjectByHandlePointer(datahandle *dh) { }..
by using a map, which contains addresses of *datahandle as an index, and addresses of *SomeObject's as value.
When SomeObject is created, it produces a group of datahandle's, which are unique for the object. Then, it passes a pointer to *datahandle and static callback function to C library开发者_运维知识库, then C library calls back and returns a pointer to datahandle, that in turn can be associated back with a SomeObject.
Which types can you recommend for storing pointer values in a map besides safe but slow <string, SomeObject*>
?
This answer tells me to avoid using auto_ptr
too.
Normally, C-like callbacks take a void* user_data
parameter, which allows you to pass in anything you want:
void c_func(void (*fptr)(void*), void* user_data){
// do some stuff
fptr(user_data);
}
Now, simply make the following static member function:
class A{
public:
static void c_callback(void* my_data){
A* my_this = static_cast<A*>(my_data);
// do stuff with my_this
}
};
Edit: According to @Martin's comment, you may get unlucky with a static member function. Better use an extern "C"
function:
extern "C" void c_callback(void* my_data){
// same as static method
}
And pass that + your A
instance to that c_func
:
int main(){
A a;
c_func(&A::c_callback,&a);
}
Or if that A
instance needs to outlive the current scope, you need to somehow save the heap-allocated pointer somewhere and delete it manually later on. A shared_ptr
or the likes won't work here, sadly. :(
On your problem of storing pointer in a map, that's not a problem at all, see this little example on Ideone.
I think this will suffice. It is what we use:
class datahandle;
class SomeObject;
typedef std::map<datahandle*, SomeObject*> pointer_map;
pointer_map my_map;
SomeObject* findSomeObjectByHandlePointer( datahandle *dh) {
pointer_map::const_iterator ff = my_map.find(dh);
if (ff != my_map.end()) {
return ii->second;
}
return NULL;
}
Often callback functions have an extra parameter of type void*
which you can use to pass in any additional data you might need. So if you want to use a member function as your callback, you pass in a pointer to the object casted to void*
and then cast it back and call the member function in your callback function.
If you have many reads and less writes, you could use vector as a set. It is very common, because lower_bound
is more effective than map
and use less space from memory:
typedef std::pair<std::string,Your_pointer> your_type;
bool your_less_function( const your_type &a, const your_type &b )
{
// your less function
return ( a < b );
}
...
std::vector<your_type> ordered-vector;
When you add values:
...
ordered-vector.push_back(value)
...
// Finally. The vector must be sorted before read.
std::sort( ordered-vector.begin(), ordered-vector.end(), your_less_function );
When ask for data:
std::vector<your_type>::iterator iter = std::lower_bound( ordered-vector.begin(), ordered-vector.end(), value, your_less_function );
if ( ( iter == ordered-vector.end() ) || your_less_function( *iter, value ) )
// you did not find the value
else
// iter contains the value
精彩评论