Skip to content

Instantly share code, notes, and snippets.

@vmolsa
Created November 15, 2016 04:27
Show Gist options
  • Save vmolsa/fc07cb1d3cf1eb513ccc89a82179ae7f to your computer and use it in GitHub Desktop.
Save vmolsa/fc07cb1d3cf1eb513ccc89a82179ae7f to your computer and use it in GitHub Desktop.
C++ Functor
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 vmolsa <ville.molsa@gmail.com> (http://github.com/vmolsa)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* class Example {
* public:
* static int Foo(const char *msg) {
* printf("%s\n", msg);
* return 1337;
* }
*
* int Bar(const char *msg) {
* printf("%s\n", msg);
* return 1337;
* }
* };
*
* Example ex;
*
* Functor<int(const char *msg)> ex1(&Example::Foo);
* Functor<int(const char *msg)> ex2 = Functor<int(const char *msg)>(&ex, &Example::Bar);
* Functor<int(const char *msg)> ex3 = [](const char *msg) {
* printf("%s\n", msg);
* return 1337;
* };
*
* int res1 = ex1("Hello World1!");
* int res2 = ex2("Hello World2!");
* int res3 = ex3("Hello World3!");
*
* printf("Ex1: %s\n", (res1 == 1337) ? "OK" : "FAILED");
* printf("Ex2: %s\n", (res2 == 1337) ? "OK" : "FAILED");
* printf("Ex3: %s\n", (res3 == 1337) ? "OK" : "FAILED");
*
*/
#ifndef FUNCTOR_H
#define FUNCTOR_H
#include <memory>
template <typename T> class Functor;
template <typename R, typename... Args> class Functor<R(Args...)> {
public:
explicit Functor() : _callback(nullptr) {}
virtual ~Functor() {
if (_callback) {
delete _callback;
}
}
template <class T> Functor(const T& functor) : _callback(new Wrap<T>(functor)) {}
template <class Object, class Method> Functor(Object *object, const Method& method) : _callback(new ObjectWrap<Object, Method>(object, method)) {}
inline R operator()(Args&&... args) const {
if (_callback) {
return _callback->Call(std::forward<Args>(args)...);
}
return R();
}
private:
class Callback {
public:
virtual ~Callback() {}
virtual R Call(Args&&... args) const = 0;
};
template <class T> class Wrap : public Callback {
public:
explicit Wrap(const T& functor) : _functor(functor) {}
~Wrap() override {}
inline virtual R Call(Args&&... args) const override {
return _functor(std::forward<Args>(args)...);
}
protected:
T _functor;
};
template <class Object, class Method> class ObjectWrap : public Callback {
public:
explicit ObjectWrap(Object *object, const Method &method) : _object(object), _method(method) {}
~ObjectWrap() override {}
inline virtual R Call(Args&&... args) const override {
if (_object) {
return (_object->*_method)(std::forward<Args>(args)...);
}
return R();
}
protected:
Object* _object;
Method _method;
};
Callback* _callback;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment