From: Emre T. <emr...@gm...> - 2011-03-19 13:22:58
|
Hi Dean. What do you say about this interface? Take a look at the various possible handlers. #include <iostream> // Fundamental meta-functions. struct my_specific_tag { }; template <typename T> struct has_a_tag { private: typedef char true_type; struct false_type { true_type _[2]; }; template <typename U> static true_type has_tag_checker(typename U::tag*); template <typename U> static false_type has_tag_checker(...); public: static const bool value = sizeof(has_tag_checker<T>(0)) == sizeof(true_type); }; template <typename T> struct has_not_a_tag { static const bool value = !has_a_tag<T>::value; }; template <bool Cond, class T = void> struct enable_if { typedef T type; }; template <class T> struct enable_if<false, T> { }; // A sample framework: #include <boost/function.hpp> #include <boost/bind.hpp> #include <string> struct data_type { data_type(const std::string& val) : value_(val) { } friend std::ostream& operator<<(std::ostream& os, const data_type& data) { return os << data.value_; } private: std::string value_; }; struct error_type { error_type(const std::string& val) : value_(val) { } friend std::ostream& operator<<(std::ostream& os, const error_type& error) { return os << error.value_; } private: std::string value_; }; struct framework { framework() : data_("No data"), error_("No error") { } template <typename T> typename enable_if<has_a_tag<T>::value>::type register_handler(T t) { priv_register_handler(t, typename T::tag()); } template <typename T> typename enable_if<has_not_a_tag<T>::value>::type register_handler(T t) { data_callback_ = boost::bind<void>(t, _1, error_); error_callback_ = boost::bind<void>(t, data_, _1); } template <typename T1, typename T2> void register_handler(T1 f1, T2 f2) { data_callback_ = f1; error_callback_ = f2; } void call(data_type data) { data_callback_(data); } void call(error_type error) { error_callback_(error); } private: template <typename T, typename U> void priv_register_handler(T t, U) { data_callback_ = boost::bind<void>(t, _1, error_); error_callback_ = boost::bind<void>(t, data_, _1); } template <typename T> void priv_register_handler(T t, my_specific_tag) { data_callback_ = boost::bind(&T::handle_data, &t, _1); error_callback_ = boost::bind(&T::handle_error, &t, _1); } private: boost::function<void(data_type)> data_callback_; boost::function<void(error_type)> error_callback_; data_type data_; error_type error_; }; // Handlers: void handler1(data_type data, error_type error) { std::cout << "handler1(" << "data: '" << data << "', " << "error: '" << error << "')" << std::endl; } struct handler2 { void operator()(data_type data, error_type error) { std::cout << "handler2(" << "data: '" << data << "', " << "error: '" << error << "')" << std::endl; } }; struct handler3 { typedef my_specific_tag tag; void handle_data(data_type data) { std::cout << "handler3(data: '" << data << "')" << std::endl; } void handle_error(error_type error) { std::cout << "handler3(error: '" << error << "')" << std::endl; } }; void handler4_data(data_type data) { std::cout << "handler4(data: '" << data << "')" << std::endl; } void handler4_error(error_type error) { std::cout << "handler4(error: '" << error << "')" << std::endl; } int main() { data_type data("data"); error_type error("error"); framework frm; frm.register_handler(handler1); frm.call(data); frm.call(error); frm.register_handler(handler2()); frm.call(data); frm.call(error); frm.register_handler(handler3()); frm.call(data); frm.call(error); frm.register_handler(handler4_data, handler4_error); frm.call(data); frm.call(error); } On Feb 24, 2011, at 10:02 AM, Dean Michael Berris wrote: > On Thu, Feb 24, 2011 at 3:55 PM, Emre Türkay <emr...@gm...> wrote: >> Hi Dean, >> >> On Feb 24, 2011, at 7:01 AM, Dean Michael Berris wrote: >> >>> Hi Emre, >>> >>> On Wed, Feb 23, 2011 at 6:22 AM, Emre Türkay <emr...@gm...> wrote: >>>> Hi folks, >>>> >>>> In file boost/network/protocol/http/server/sync_connection.http (in sync_connection::start), line 57, there is a call to Handler::log(string). >>>> 1. This conflicts with the documentation, where there is no hello_world::log() method implemented in the simple http server example. >>>> 2. Do we really need to keep it that way, i.e., we can make boost::system::system_error an extra argument to the handler function (like asio handlers). By this way, it would even be possible to implement a handler with a free standing function and pass the http::server a ptr to function instead of a functor, for simple cases. >>>> >>>> What you think? >>>> >>> >>> I like #2 -- do you have a pull request? :) >> >> No, I wanted to ask before diving in. I'm still reading the docs ;) I'll try if I can make it. >> > > Cool, no worries. :) > > I suggest looking at the cases where the log function is called -- I > think calling the handler with an extra error argument is a little > confusing. I like the approach of providing an error handling function > to the constructor of the HTTP server, and if one isn't provided a > default error handler is provided that optionally prints information > to standard error. There was a suggestion to use Boost.Log but I don't > see how this could be done with Boost.Log not yet being in the > releases (last I checked). > > This should be easy to do and I would really appreciate it if you can > give that a shot -- as I have very limited time at the moment to be > able to work on the library. > > Have a good one and I look forward to your pull requests! > > -- > Dean Michael Berris > about.me/deanberris |