简体   繁体   中英

How to legally cast function pointer to method pointer?

I'm looking for the opposite of std::mem_fn : turning a function pointer into a member pointer (eg void(*)(C*) to void(C::*)() for a given class C ).

Background

I'm using a 3rd party library (say lib1.h ) to create bindings for another 3rd party library ( lib2.h ).

Some functions in lib1.h receive method pointers to methods that accept a Value argument (also defined in lib1.h ). In other hand, lib2.h classes do not contain such methods, so I have to do the wrappings manually through a lambda function:

/* lib1.h (can't touch this) */ 
class Value;
class Property;

template <typename C>
struct ObjectWrap {
  using Method = void(C::*)(Value);
  static Property declare(std::string name, Method method); 
};

/* lib2.h (can't touch this) */ 
struct Person {
  void greet(std::string name);
};

/* bindings.cpp */
std::string value_to_std_string(Value v);

Property declarePersonGreet() {
  return ObjectWrap<Person>::declare("greet",
    /* ERROR */ [](Person* p, Value v) {
      p->greet(value_to_std_string(v));
  });
}

I'm fairly confident that I'm not misusing lib1.h 's API (and implementing such methods by deriving the classes of lib2.h is unfortunately not an option). Therefore I feel that casting to method pointers is the only solution.

Is there any way of legally doing this? I would like to avoid undefined behavior if possible.

No you cannot do such cast. Even if you could get a void(Person::*)(Value) , you could not use that because Person has no such method. If lib1 expects a type C with a member function void(C::)(Value) then there is no way around providing such type C with the corresponding method. You can write a wrapper for Person :

struct Wrapper {    
    Person p;
    void greet(Value v) {
        p.greet(value_to_std_string(v));
    }
};


Property declarePersonGreet() {
  return ObjectWrap<Wrapper>::declare("greet",&Wrapper::greet);
}

If you have many classes similar to Person you could make the wrapper a template:

template <typename T>
struct Wrapper {    
    T p;
    void greet(Value v) {
        p.greet(value_to_std_string(v));
    }
};

...possibly also parameterized on the member function to be called on the wrapped object and the function to be used for converting the parameter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM