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