
On Sun, 25 Mar 2012 00:15:38 +0100, lcaminiti <lorcaminiti@gmail.com> wrote:
How's this different from: http://svn.boost.org/svn/boost/trunk/libs/functional/overloaded_function/doc...
Hi Lorenzo, (Boost.)Overload is a dynamic wrapper of multiple callable objects. All started from a Joel de Guzman's post where he showed a proof of concept of a thin-wrapper of several Boost.Functions. See: http://lists.boost.org/Archives/boost/2007/09/127906.php On that code base, I designed (Boost.)Overload that provides an interface similar to Boost.Function. A first difference is that with (Boost.)Overload is possible to create an empty boost::overload object, and then set up callable targets at a later time, obviously the library provides methods for checking if a given callable target is empty. That matches exactly what Boost.Function does. Here's a basic example extracted from the tutorial: ///////////////////////////////////////////////////////////////// #include <boost/detail/lightweight_test.hpp> #include <boost/overload.hpp> int int_sum(int x, int y) { return x + y; } float float_inc(float x ) { return x + 1.0f; } int main() { boost::overload<int (int, int ), float (float )> f; f.set(&int_sum); // here automatic call signature f.set(&float_inc); // deduction occurs int r1 = f(1, 2); // invokes int_sum float r2 = f(3.0f); // invokes float_inc BOOST_ASSERT( r1 == 3 ); BOOST_ASSERT( r2 == 4.0f ); return boost::report_errors(); } ///////////////////////////////////////////////////////////////// One can set all callable targets at once: f.set(&float_inc, &int_sum). Order does not matter, the callable entity is assigned automatically to the embedded boost::function with a matching call signature. However that works for monomorphic callable objects only. For polymorphic one it is needed to utilize the set method based on the call signature syntax: ///////////////////////////////////////////////////////////////// #include <boost/detail/lightweight_test.hpp> #include <boost/overload.hpp> /* polymorphic function object */ struct bar { int operator()(int ) { return 1; } template<typename T> int operator()(T ) { return ( 2 + sizeof(T) ); } }; int main() { boost::overload<int (int ), int (char ), int (double )> f; // function object bar foo; // we use the call signature syntax for setting a copy of // foo as object target for the call signature int (char ) // only f.set<int (char )>(foo); // invokes int foo(char ) template instantiation BOOST_ASSERT( f('x') == foo('x') ); // through the empty<Signature>() method we check // that no other object target has been set up BOOST_ASSERT( f.empty<int(int )>() ); BOOST_ASSERT( f.empty<int(double )>() ); // now we set a copy of foo as object target tied to // the call signature int( int ) f.set<int (int )>(foo); BOOST_ASSERT( f('x') == foo('x') ); BOOST_ASSERT( f(1) == foo(1) ); BOOST_ASSERT( f.empty<int(double )>() ); // and finally we set up also the object target // for the int(double ) call signature f.set<int (double )>(foo); BOOST_ASSERT( f('x') == foo('x') ); BOOST_ASSERT( f(1) == foo(1) ); BOOST_ASSERT( f(1.0) == foo(1.0) ); return boost::report_errors(); } ///////////////////////////////////////////////////////////////// In case we are dealing with a statefull function object copying it several times is both expensive and probably also semantically incorrect. The solution is to wrap the function object with boost::ref. The call signature based syntax can be used with overloaded free and member functions, too. Another point where the two libraries differ is that a boost::overload object that supports a given call signature S can be passed everywhere an object of type boost::function<S> is expected. Lately I implemented also support for boost::result_of. So it is possible to utilize (Boost.)Overload with Boost.Fusion algorithms such as boost::fusion::for_each. A natural use case is to utilize (Boost.)Overload for generating a Boost.Variant visitor: ///////////////////////////////////////////////////////////////// #include <boost/variant.hpp> #include <boost/detail/lightweight_test.hpp> #include <boost/overload.hpp> template< typename Overload, typename R = ::boost::detail::static_visitor_default_return
struct overloaded_visitor : public Overload { typedef R result_type; }; int apply_to_int(int ) { return 1; } int apply_to_string(const std::string & ) { return 2; } typedef boost::overload<int (int ), int(const std::string & )> overload_type; typedef overloaded_visitor<overload_type, int> visitor_type; int main() { boost::variant< int, std::string > u("hello world"); visitor_type my_visitor; my_visitor.set( &apply_to_int, &apply_to_string ); int result = boost::apply_visitor( my_visitor, u ); BOOST_ASSERT( result == 2 ); return boost::report_errors(); } ///////////////////////////////////////////////////////////////// You can find more details on the documentation page: http://svn.boost.org/svn/boost/sandbox/overload/trunk/libs/overload/docs/htm... Kind Regards, -- Marco -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/