#include <algorithm>
#include <functional>
#include <iomanip>
#include <iostream>
#include <memory>
#include <vector>
using std::size_t;
struct Tested;
class CallChecker
{
public:
typedef void (Tested::*Call)();
template <class T>
struct type_identity { typedef T type; };
template <class T>
using type = typename type_identity<T>::type; //used to prevent deduction
template <class R, class... A>
void addCheck(R (Tested::*call)(A...), type<std::function<bool (A...)>> check)
{
auto key = reinterpret_cast<Call>(call);
mChecks.emplace_back(key, std::make_shared<CheckImpl<A...>>(std::move(check)));
}
template <class R, class... A>
bool checkCall(R (Tested::*call)(A...), type<A>... arg)
{
auto key = reinterpret_cast<Call>(call);
auto hasKey = [key](const std::pair<Call, std::shared_ptr<Check>> &p)
{ return p.first == key; };
for (
auto it = std::find_if(begin(mChecks), end(mChecks), hasKey);
it != end(mChecks);
it = std::find_if(++it, end(mChecks), hasKey)
)
{
auto *check = static_cast<CheckImpl<A...>*>(it->second.get());
if (check->mCheck(arg...))
return true;
}
return false;
}
private:
struct Check
{
virtual ~Check() {}
};
template <class... A>
struct CheckImpl : Check
{
std::function<bool (A...)> mCheck;
CheckImpl(std::function<bool (A...)> check) : mCheck(std::move(check)) {}
};
std::vector<std::pair<Call, std::shared_ptr<Check>>> mChecks;
};
struct Tested : public CallChecker
{
void foo() { std::cout << "foo: " << checkCall(&Tested::foo) << '\n'; }
void bar(std::string s, int i) { std::cout << "bar: " << checkCall(&Tested::bar, std::move(s), i) << '\n'; }
};
int main() {
std::cout << std::boolalpha;
Tested test;
test.addCheck(&Tested::foo, [] { return true; });
test.foo();
test.bar("adams", 42);
test.addCheck(&Tested::bar, [](std::string s, int i) { return s == "adams" && i == 42; });
test.bar("adams", 42);
test.bar("douglas", 42);
return 0;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb21hbmlwPgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxtZW1vcnk+CiNpbmNsdWRlIDx2ZWN0b3I+Cgp1c2luZyBzdGQ6OnNpemVfdDsKCnN0cnVjdCBUZXN0ZWQ7CgoKY2xhc3MgQ2FsbENoZWNrZXIKewpwdWJsaWM6Cgl0eXBlZGVmIHZvaWQgKFRlc3RlZDo6KkNhbGwpKCk7CgkKCXRlbXBsYXRlIDxjbGFzcyBUPgoJc3RydWN0IHR5cGVfaWRlbnRpdHkgeyB0eXBlZGVmIFQgdHlwZTsgfTsKCXRlbXBsYXRlIDxjbGFzcyBUPgoJdXNpbmcgdHlwZSA9IHR5cGVuYW1lIHR5cGVfaWRlbnRpdHk8VD46OnR5cGU7ICAvL3VzZWQgdG8gcHJldmVudCBkZWR1Y3Rpb24KCgl0ZW1wbGF0ZSA8Y2xhc3MgUiwgY2xhc3MuLi4gQT4KCXZvaWQgYWRkQ2hlY2soUiAoVGVzdGVkOjoqY2FsbCkoQS4uLiksIHR5cGU8c3RkOjpmdW5jdGlvbjxib29sIChBLi4uKT4+IGNoZWNrKQoJewoJCWF1dG8ga2V5ID0gcmVpbnRlcnByZXRfY2FzdDxDYWxsPihjYWxsKTsKCQltQ2hlY2tzLmVtcGxhY2VfYmFjayhrZXksIHN0ZDo6bWFrZV9zaGFyZWQ8Q2hlY2tJbXBsPEEuLi4+PihzdGQ6Om1vdmUoY2hlY2spKSk7Cgl9CgkKCXRlbXBsYXRlIDxjbGFzcyBSLCBjbGFzcy4uLiBBPgoJYm9vbCBjaGVja0NhbGwoUiAoVGVzdGVkOjoqY2FsbCkoQS4uLiksIHR5cGU8QT4uLi4gYXJnKQoJewoJCWF1dG8ga2V5ID0gcmVpbnRlcnByZXRfY2FzdDxDYWxsPihjYWxsKTsKCQlhdXRvIGhhc0tleSA9IFtrZXldKGNvbnN0IHN0ZDo6cGFpcjxDYWxsLCBzdGQ6OnNoYXJlZF9wdHI8Q2hlY2s+PiAmcCkKCQkJeyByZXR1cm4gcC5maXJzdCA9PSBrZXk7IH07CgkJZm9yICgKCQkJYXV0byBpdCA9IHN0ZDo6ZmluZF9pZihiZWdpbihtQ2hlY2tzKSwgZW5kKG1DaGVja3MpLCBoYXNLZXkpOwoJCQlpdCAhPSBlbmQobUNoZWNrcyk7CgkJCWl0ID0gc3RkOjpmaW5kX2lmKCsraXQsIGVuZChtQ2hlY2tzKSwgaGFzS2V5KQoJCSkKCQl7CgkJCWF1dG8gKmNoZWNrID0gc3RhdGljX2Nhc3Q8Q2hlY2tJbXBsPEEuLi4+Kj4oaXQtPnNlY29uZC5nZXQoKSk7CgkJCWlmIChjaGVjay0+bUNoZWNrKGFyZy4uLikpCgkJCQlyZXR1cm4gdHJ1ZTsKCQl9CgkJcmV0dXJuIGZhbHNlOwoJfQoKcHJpdmF0ZToKCXN0cnVjdCBDaGVjawoJewoJCXZpcnR1YWwgfkNoZWNrKCkge30KCX07CgkKCXRlbXBsYXRlIDxjbGFzcy4uLiBBPgoJc3RydWN0IENoZWNrSW1wbCA6IENoZWNrCgl7CgkJc3RkOjpmdW5jdGlvbjxib29sIChBLi4uKT4gbUNoZWNrOwoJCQoJCUNoZWNrSW1wbChzdGQ6OmZ1bmN0aW9uPGJvb2wgIChBLi4uKT4gY2hlY2spIDogbUNoZWNrKHN0ZDo6bW92ZShjaGVjaykpIHt9Cgl9OwoKCXN0ZDo6dmVjdG9yPHN0ZDo6cGFpcjxDYWxsLCBzdGQ6OnNoYXJlZF9wdHI8Q2hlY2s+Pj4gbUNoZWNrczsKfTsKCgpzdHJ1Y3QgVGVzdGVkIDogcHVibGljIENhbGxDaGVja2VyCnsKCXZvaWQgZm9vKCkgeyBzdGQ6OmNvdXQgPDwgImZvbzogIiA8PCBjaGVja0NhbGwoJlRlc3RlZDo6Zm9vKSA8PCAnXG4nOyB9CgkKCXZvaWQgYmFyKHN0ZDo6c3RyaW5nIHMsIGludCBpKSB7IHN0ZDo6Y291dCA8PCAiYmFyOiAiIDw8IGNoZWNrQ2FsbCgmVGVzdGVkOjpiYXIsIHN0ZDo6bW92ZShzKSwgaSkgPDwgJ1xuJzsgfQp9OwoKaW50IG1haW4oKSB7CglzdGQ6OmNvdXQgPDwgc3RkOjpib29sYWxwaGE7CglUZXN0ZWQgdGVzdDsKCXRlc3QuYWRkQ2hlY2soJlRlc3RlZDo6Zm9vLCBbXSB7IHJldHVybiB0cnVlOyB9KTsKCXRlc3QuZm9vKCk7Cgl0ZXN0LmJhcigiYWRhbXMiLCA0Mik7Cgl0ZXN0LmFkZENoZWNrKCZUZXN0ZWQ6OmJhciwgW10oc3RkOjpzdHJpbmcgcywgaW50IGkpIHsgcmV0dXJuIHMgPT0gImFkYW1zIiAmJiBpID09IDQyOyB9KTsKCXRlc3QuYmFyKCJhZGFtcyIsIDQyKTsKCXRlc3QuYmFyKCJkb3VnbGFzIiwgNDIpOwoJcmV0dXJuIDA7Cn0=