Inspired by an article at the CUJ from Andrei Alexandrescu, I was finally able to come up with a compose_f_gxy_hxy-adapter. I think that it's the missing adapter to make compose.hpp complete. In the companies production code, I needed it and used a much easier implementation with some limitations, so it's not just a toy example.
The code attached is a first cut, tested on Intel C++ 7.1 and GCC 3.3. The GCC 2.95.3 has problems with it I haven't solved yet (and I don't know if it's possible at all). Anyway, I'd like to hear some comments whether it's a good idea and should be pushed forward or if it better be buried :) I attached a modified compose.hpp and a new file for the same directory where I put the type selection code, called combined_argument_type.hpp. It needs some boostification and you need to read Andrei's article to understand it. Really. :) Andrei's article can be found here: http://www.cuj.com/documents/s=7996/cujcexp1904alexandr/alexandr.htm As I put the implementation into a separate file, it should now also be easy for boost to provide min/max (probably in utility.hpp?) like suggested by Andrei if requested - although I'm not totally convinced it's a good idea as IMHO min/max should have value semantics (the currently have AFAICS) and not reference-semantics, but that's another story. To complete the implementation of combined_argument_type, it would help if mpl::vector would have 16 instead of 10 arguments, but that can be done later if there is interest in compose_f_gxy_hxy. I currently simply removed the first types of the type-list, I've just been lazy, so don't wonder how this should work. It won't. :) Comments? Regards, Daniel
// Add some nice header here... :) #ifndef BOOST_COMBINED_ARGUMENT_TYPE_HPP #define BOOST_COMBINED_ARGUMENT_TYPE_HPP #include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_const.hpp> #include <boost/type_traits/remove_const.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/find.hpp> #include <boost/mpl/if.hpp> namespace boost { template< typename L, typename R > struct combined_argument_type { private: typedef mpl::vector< const bool, const char, const signed char, const unsigned char, const wchar_t, const short, const unsigned short > cutted_types; // GRRR, vector should allow 16 elements! typedef mpl::vector< const int, const unsigned int, const long, const unsigned long, const long long, const unsigned long long, const float, const double, const long double > sorted_types; typedef typename remove_const< L >::type non_const_L; typedef typename remove_const< R >::type non_const_R; enum { is_const_L = ( is_const< L >::value || !is_const< R >::value ), is_const_R = ( is_const< R >::value || !is_const< L >::value ), pos_L = mpl::find< sorted_types, const L >::type::pos::value, pos_R = mpl::find< sorted_types, const R >::type::pos::value, l2r = is_const_R && is_convertible< non_const_L&, non_const_R& >::value, r2l = is_const_L && is_convertible< non_const_R&, non_const_L& >::value }; typedef typename mpl::if_< is_convertible< R, L >, L, R >::type T1; typedef typename mpl::if_c< ( pos_L != -1 ) && ( pos_L < pos_R ), R, T1 >::type T2; typedef typename mpl::if_c< l2r, R&, T2 >::type T3; public: typedef typename mpl::if_c< r2l, L&, T3 >::type type; }; } // namespace boost #endif // BOOST_COMBINED_ARGUMENT_TYPE_HPP
/* supplementing compose function objects * Fri Jul 16 21:01:58 MEST 1999 */ /* The following code example is taken from the book * "The C++ Standard Library - A Tutorial and Reference" * by Nicolai M. Josuttis, Addison-Wesley, 1999 * * (C) Copyright Nicolai M. Josuttis 1999. * Permission to copy, use, modify, sell and distribute this software * is granted provided this copyright notice appears in all copies. * This software is provided "as is" without express or implied * warranty, and with no claim as to its suitability for any purpose. */ // See http://www.boost.org/libs/compose for Documentation. #ifndef BOOST_COMPOSE_HPP #define BOOST_COMPOSE_HPP #include <functional> #include <boost/combined_argument_type.hpp> namespace boost { /********************************************************** * type nullary_function * - as supplement to unary_function and binary_function **********************************************************/ template <class Result> struct nullary_function { typedef Result result_type; }; /********************************************************** * ptr_fun for functions with no argument **********************************************************/ template <class Result> class pointer_to_nullary_function : public nullary_function<Result> { protected: Result (*ptr)(); public: pointer_to_nullary_function() { } explicit pointer_to_nullary_function(Result (*x)()) : ptr(x) { } Result operator()() const { return ptr(); } }; template <class Result> inline pointer_to_nullary_function<Result> ptr_fun(Result (*x)()) { return pointer_to_nullary_function<Result>(x); } /*********** compose_f_gx_t and compose_f_gx **********************/ /* class for the compose_f_gx adapter */ template <class OP1, class OP2> class compose_f_gx_t : public std::unary_function<typename OP2::argument_type, typename OP1::result_type> { private: OP1 op1; // process: op1(op2(x)) OP2 op2; public: // constructor compose_f_gx_t(const OP1& o1, const OP2& o2) : op1(o1), op2(o2) { } // function call typename OP1::result_type operator()(const typename OP2::argument_type& x) const { return op1(op2(x)); } }; /* convenience functions for the compose_f_gx adapter */ template <class OP1, class OP2> inline compose_f_gx_t<OP1,OP2> compose_f_gx (const OP1& o1, const OP2& o2) { return compose_f_gx_t<OP1,OP2>(o1,o2); } /*********** compose_f_gx_hx_t and compose_f_gx_hx **********************/ /* class for the compose_f_gx_hx adapter */ template <class OP1, class OP2, class OP3> class compose_f_gx_hx_t : public std::unary_function<typename OP2::argument_type, typename OP1::result_type> { private: OP1 op1; // process: op1(op2(x),op3(x)) OP2 op2; OP3 op3; public: // constructor compose_f_gx_hx_t (const OP1& o1, const OP2& o2, const OP3& o3) : op1(o1), op2(o2), op3(o3) { } // function call typename OP1::result_type operator()(const typename OP2::argument_type& x) const { return op1(op2(x),op3(x)); } }; /* convenience functions for the compose_f_gx_hx adapter */ template <class OP1, class OP2, class OP3> inline compose_f_gx_hx_t<OP1,OP2,OP3> compose_f_gx_hx (const OP1& o1, const OP2& o2, const OP3& o3) { return compose_f_gx_hx_t<OP1,OP2,OP3>(o1,o2,o3); } /*********** compose_f_gxy_t and compose_f_gxy **********************/ /* class for the compose_f_gxy adapter */ template <class OP1, class OP2> class compose_f_gxy_t : public std::binary_function<typename OP2::first_argument_type, typename OP2::second_argument_type, typename OP1::result_type> { private: OP1 op1; // process: op1(op2(x,y)) OP2 op2; public: // constructor compose_f_gxy_t (const OP1& o1, const OP2& o2) : op1(o1), op2(o2) { } // function call typename OP1::result_type operator()(const typename OP2::first_argument_type& x, const typename OP2::second_argument_type& y) const { return op1(op2(x,y)); } }; /* convenience function for the compose_f_gxy adapter */ template <class OP1, class OP2> inline compose_f_gxy_t<OP1,OP2> compose_f_gxy (const OP1& o1, const OP2& o2) { return compose_f_gxy_t<OP1,OP2>(o1,o2); } /*********** compose_f_gx_hy_t and compose_f_gx_hy **********************/ /* class for the compose_f_gx_hy adapter */ template <class OP1, class OP2, class OP3> class compose_f_gx_hy_t : public std::binary_function<typename OP2::argument_type, typename OP3::argument_type, typename OP1::result_type> { private: OP1 op1; // process: op1(op2(x),op3(y)) OP2 op2; OP3 op3; public: // constructor compose_f_gx_hy_t (const OP1& o1, const OP2& o2, const OP3& o3) : op1(o1), op2(o2), op3(o3) { } // function call typename OP1::result_type operator()(const typename OP2::argument_type& x, const typename OP3::argument_type& y) const { return op1(op2(x),op3(y)); } }; /* convenience function for the compose_f_gx_hy adapter */ template <class OP1, class OP2, class OP3> inline compose_f_gx_hy_t<OP1,OP2,OP3> compose_f_gx_hy (const OP1& o1, const OP2& o2, const OP3& o3) { return compose_f_gx_hy_t<OP1,OP2,OP3>(o1,o2,o3); } /*********** compose_f_g_t and compose_f_g **********************/ /* class for the compose_f_g adapter */ template <class OP1, class OP2> class compose_f_g_t : public boost::nullary_function<typename OP1::result_type> { private: OP1 op1; // process: op1(op2()) OP2 op2; public: // constructor compose_f_g_t(const OP1& o1, const OP2& o2) : op1(o1), op2(o2) { } // function call typename OP1::result_type operator()() const { return op1(op2()); } }; /* convenience functions for the compose_f_g adapter */ template <class OP1, class OP2> inline compose_f_g_t<OP1,OP2> compose_f_g (const OP1& o1, const OP2& o2) { return compose_f_g_t<OP1,OP2>(o1,o2); } /*********** compose_f_gxy_hxy_t and compose_f_gxy_hxy ******************/ /* class for the compose_f_gxy_hxy adapter */ template <class OP1, class OP2, class OP3> class compose_f_gxy_hxy_t : public std::binary_function<typename combined_argument_type<typename OP2::first_argument_type, typename OP3::first_argument_type>::type, typename combined_argument_type<typename OP2::second_argument_type, typename OP3::second_argument_type>::type, typename OP1::result_type> { private: OP1 op1; // process: op1(op2(x,y),op3(x,y)) OP2 op2; OP3 op3; public: // constructor compose_f_gxy_hxy_t (const OP1& o1, const OP2& o2, const OP3& o3) : op1(o1), op2(o2), op3(o3) { } // function call typename OP1::result_type operator()(const typename combined_argument_type<typename OP2::first_argument_type, typename OP3::first_argument_type>::type& x, const typename combined_argument_type<typename OP2::second_argument_type, typename OP3::second_argument_type>::type& y) const { return op1(op2(x,y),op3(x,y)); } }; /* convenience function for the compose_f_gxy_hxy adapter */ template <class OP1, class OP2, class OP3> inline compose_f_gxy_hxy_t<OP1,OP2,OP3> compose_f_gxy_hxy (const OP1& o1, const OP2& o2, const OP3& o3) { return compose_f_gxy_hxy_t<OP1,OP2,OP3>(o1,o2,o3); } } /* namespace boost */ #endif /*BOOST_COMPOSE_HPP*/
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost