|
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
|