#include <utility>
#include <cassert>
template<typename T, typename R, typename ...Args>
class mem_fun_t {
using method_ptr_t = R (T::*)(Args...);
public:
mem_fun_t(method_ptr_t const methodPtr_) : methodPtr_(methodPtr_) {
assert(methodPtr_);
}
R operator ()(T * const objectPtr, Args && ...args) const {
assert(objectPtr);
return (objectPtr->*methodPtr_)(std::forward<Args>(args)...);
}
R operator ()(T & objectRef, Args && ...args) const {
return (objectRef.*methodPtr_)(std::forward<Args>(args)...);
}
private:
method_ptr_t const methodPtr_;
};
template<typename T, typename R, typename ...Args>
mem_fun_t<T, R, Args...> mem_fun(R (T::*pointer)(Args...)) {
return {pointer};
}
template<typename T, typename R, typename ...Args>
mem_fun_t<T const, R, Args...> mem_fun(R (T::*pointer)(Args...) const) {
return {pointer};
}
struct test {
int mutable_method(float f, double d) {
return static_cast<int>(f + d);
}
int const_method(float f, double d) const {
return static_cast<int>(f + d);
}
};
int main() {
test mutableObject;
test const constObject;
auto const mutableBinded = mem_fun(&test::mutable_method);
assert(mutableBinded(&mutableObject, 5.56f, 7.91) == 13);
assert(mutableBinded(mutableObject, 78.9f, 1.2) == 80);
auto const constBinded = mem_fun(&test::const_method);
assert(constBinded(&mutableObject, 4.51f, 13.6) == 18);
assert(constBinded(&constObject, -123.1f, 45.5) == -77);
assert(constBinded(mutableObject, -98.f, 56.4) == -41);
assert(constBinded(constObject, 45.56f, 45.5) == 91);
}
I2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDxjYXNzZXJ0PgoKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFIsIHR5cGVuYW1lIC4uLkFyZ3M+CmNsYXNzIG1lbV9mdW5fdCB7CgogICB1c2luZyBtZXRob2RfcHRyX3QgPSBSIChUOjoqKShBcmdzLi4uKTsKCnB1YmxpYzoKICAgbWVtX2Z1bl90KG1ldGhvZF9wdHJfdCBjb25zdCBtZXRob2RQdHJfKSA6IG1ldGhvZFB0cl8obWV0aG9kUHRyXykgewogICAgICBhc3NlcnQobWV0aG9kUHRyXyk7CiAgIH0KCiAgIFIgb3BlcmF0b3IgKCkoVCAqIGNvbnN0IG9iamVjdFB0ciwgQXJncyAmJiAuLi5hcmdzKSBjb25zdCB7CiAgICAgIGFzc2VydChvYmplY3RQdHIpOwogICAgICByZXR1cm4gKG9iamVjdFB0ci0+Km1ldGhvZFB0cl8pKHN0ZDo6Zm9yd2FyZDxBcmdzPihhcmdzKS4uLik7CiAgIH0KCiAgIFIgb3BlcmF0b3IgKCkoVCAmIG9iamVjdFJlZiwgQXJncyAmJiAuLi5hcmdzKSBjb25zdCB7CiAgICAgIHJldHVybiAob2JqZWN0UmVmLiptZXRob2RQdHJfKShzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4pOwogICB9Cgpwcml2YXRlOgogICBtZXRob2RfcHRyX3QgY29uc3QgbWV0aG9kUHRyXzsKfTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFIsIHR5cGVuYW1lIC4uLkFyZ3M+Cm1lbV9mdW5fdDxULCBSLCBBcmdzLi4uPiBtZW1fZnVuKFIgKFQ6Oipwb2ludGVyKShBcmdzLi4uKSkgewogICByZXR1cm4ge3BvaW50ZXJ9Owp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBSLCB0eXBlbmFtZSAuLi5BcmdzPgptZW1fZnVuX3Q8VCBjb25zdCwgUiwgQXJncy4uLj4gbWVtX2Z1bihSIChUOjoqcG9pbnRlcikoQXJncy4uLikgY29uc3QpIHsKICAgcmV0dXJuIHtwb2ludGVyfTsKfQoKCnN0cnVjdCB0ZXN0IHsKCiAgIGludCBtdXRhYmxlX21ldGhvZChmbG9hdCBmLCBkb3VibGUgZCkgewogICAgICByZXR1cm4gc3RhdGljX2Nhc3Q8aW50PihmICsgZCk7CiAgIH0KCiAgIGludCBjb25zdF9tZXRob2QoZmxvYXQgZiwgZG91YmxlIGQpIGNvbnN0IHsKICAgICAgcmV0dXJuIHN0YXRpY19jYXN0PGludD4oZiArIGQpOwogICB9Cn07CgoKaW50IG1haW4oKSB7CiAgIHRlc3QgbXV0YWJsZU9iamVjdDsKICAgdGVzdCBjb25zdCBjb25zdE9iamVjdDsgCgogICBhdXRvIGNvbnN0IG11dGFibGVCaW5kZWQgPSBtZW1fZnVuKCZ0ZXN0OjptdXRhYmxlX21ldGhvZCk7CiAgIGFzc2VydChtdXRhYmxlQmluZGVkKCZtdXRhYmxlT2JqZWN0LCA1LjU2ZiwgNy45MSkgPT0gMTMpOwogICBhc3NlcnQobXV0YWJsZUJpbmRlZChtdXRhYmxlT2JqZWN0LCA3OC45ZiwgMS4yKSA9PSA4MCk7ICAgCgogICBhdXRvIGNvbnN0IGNvbnN0QmluZGVkID0gbWVtX2Z1bigmdGVzdDo6Y29uc3RfbWV0aG9kKTsKICAgYXNzZXJ0KGNvbnN0QmluZGVkKCZtdXRhYmxlT2JqZWN0LCA0LjUxZiwgMTMuNikgPT0gMTgpOwogICBhc3NlcnQoY29uc3RCaW5kZWQoJmNvbnN0T2JqZWN0LCAtMTIzLjFmLCA0NS41KSA9PSAtNzcpOwogICBhc3NlcnQoY29uc3RCaW5kZWQobXV0YWJsZU9iamVjdCwgLTk4LmYsIDU2LjQpID09IC00MSk7CiAgIGFzc2VydChjb25zdEJpbmRlZChjb25zdE9iamVjdCwgNDUuNTZmLCA0NS41KSA9PSA5MSk7ICAgCn0K