开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜