Last active
July 29, 2017 17:01
-
-
Save austo/5676ce0a1bfd129d992d4f1b79868eef to your computer and use it in GitHub Desktop.
call based on type
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <functional> | |
| #include <iostream> | |
| #include <string> | |
| #include <vector> | |
| // clang++ -std=c++11 -stdlib=libc++ -Wall handler_wrap.cpp -o handler_wrap | |
| // g++ -std=c++11 -Wall handler_wrap.cpp -o handler_wrap | |
| // Message Type #1 | |
| class Foo { | |
| std::string d_payload; | |
| public: | |
| Foo(const std::string& payload) : d_payload(payload) {} | |
| const std::string& payload() const { return d_payload; } | |
| enum { TYPE_ID = 1 }; | |
| }; | |
| // Message Type #2 | |
| class Bar { | |
| int d_weight; | |
| std::string d_payload; | |
| public: | |
| Bar(const std::string& payload) | |
| : d_weight(payload.length()), d_payload(payload) {} | |
| const std::string& payload() const { return d_payload; } | |
| const int& weight() const { return d_weight; } | |
| enum { TYPE_ID = 2 }; | |
| }; | |
| // "Raw" message | |
| struct Blob { | |
| int d_type_id; | |
| std::string d_payload; | |
| Blob(int type_id, std::string payload) | |
| : d_type_id(type_id), d_payload(payload) {} | |
| }; | |
| // Wrapper with consistent interface | |
| template <typename T> | |
| class HandlerWrapper { | |
| std::function<void(T&)> m_handler; | |
| public: | |
| explicit HandlerWrapper(std::function<void(const T&)> handler) | |
| : m_handler(handler) {} | |
| void operator()(const Blob& blob) { | |
| if (blob.d_type_id == T::TYPE_ID) { | |
| T msg(blob.d_payload); | |
| m_handler(msg); | |
| } | |
| } | |
| }; | |
| class Registry { | |
| std::vector<std::function<void(const Blob&)>> m_handlers; | |
| public: | |
| Registry() : m_handlers() {} | |
| // Single registration function (w/overload for raw function pointers) | |
| template <typename T> | |
| Registry& addHandler(std::function<void(const T&)> handler) { | |
| m_handlers.emplace_back(HandlerWrapper<T>(handler)); | |
| return *this; | |
| } | |
| template <typename T> | |
| Registry& addHandler(void (*handler)(const T&)) { | |
| return addHandler(std::function<void(const T&)>(handler)); | |
| } | |
| void call(std::vector<Blob> blobs) { | |
| for (auto it = blobs.begin(); it != blobs.end(); ++it) { | |
| for (auto f = m_handlers.begin(); f != m_handlers.end(); ++f) { | |
| (*f)(*it); | |
| } | |
| } | |
| } | |
| }; | |
| // Backing function (would most likely be a mem_fun reference) | |
| void fooHandler(const Foo& foo) { | |
| std::cout << "Foo: " << foo.payload() << std::endl; | |
| } | |
| void barHandler(const Bar& bar) { | |
| std::cout << "Bar: (" << bar.payload() << ", " << bar.weight() << ")" | |
| << std::endl; | |
| } | |
| int main(int argc, char** argv) { | |
| std::vector<Blob> blobs{Blob(1, "Blob 1"), Blob(2, "Blob 2"), | |
| Blob(1, "Blob 3"), Blob(2, "Blob 4")}; | |
| Registry r1; | |
| std::cout << "With raw function pointers:" << std::endl; | |
| r1.addHandler(&fooHandler).addHandler(&barHandler).call(blobs); | |
| // Client responsible for creating these from whatever | |
| std::function<void(const Foo&)> f1(fooHandler); | |
| std::function<void(const Bar&)> f2(barHandler); | |
| Registry r2; | |
| std::cout << "\nWith std::functions:" << std::endl; | |
| r2.addHandler(f1).addHandler(f2).call(blobs); | |
| std::function<void(const Bar&)> f3([](const Bar& b) { | |
| std::cout << "Bar lambda -> "; | |
| barHandler(b); | |
| }); | |
| Registry r3; | |
| std::cout | |
| << "\nWith mix of raw function pointers, std::functions and lambdas:" | |
| << std::endl; | |
| r3.addHandler(fooHandler) | |
| .addHandler(f1) | |
| .addHandler(barHandler) | |
| .addHandler(f3) | |
| .call(blobs); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment