On Sep 24, 11:29 pm, Ulrich Eckhardt <eckha...@satorlaser.com> wrote:
> Really? You first need both the 666 and the 'E', which are IIUC the results
> of the two function calls, so typically one of them is wasted. That's also
> why I'd use a less complicated one:
> int int_function();
> char char_function();
> struct proxy {
> operator int() const {
> return int_function();
> }
> operator char() const {
> return char_function();
> }
> };
> proxy function() {
> return proxy();
> }
Your idea is very interesting, just amazing in fact, I've expanded it
a bit, probably it will be useful for somebody. Using it, it is
possible to provide any number of overloading functions, for example
with the following way:
char f_char()
{std::cout<<"f_char()\n";return char();}
int f_int()
{std::cout<<"f_int()\n";return int();}
short f_short(int) //!! Function accepts parameter
{std::cout<<"f_short()\n";return short();}
char a = f(f_char); // prints "f_char()"
int b = f(f_char, f_int); // prints "f_int()"
char c = f(f_char, f_int); // prints "f_char()"
short d = f(f_char, boost::bind(f_short,5)); //!! Binders
allowed // prints "f_short()"
int e = f(f_int, f_short); //!! Function without binded parameter
allowed // prints "f_int()"
char f = f(f_char, f_char); //!! Cause compilation error because of
ambiguity
So, the implementation itself below (yeah, I know, this code is not
ideal :-) ):
#include <boost/mpl/list.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/preprocessor/repetition.hpp>
#include <boost/type_traits/function_traits.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/is_pointer.hpp>
// Maximum number of overload variants
#ifndef RETTYPE_OVERLOAD_MAX_COUNT
#define RETTYPE_OVERLOAD_MAX_COUNT 10
#endif
namespace{
// Just a static check used to verify that all types in the
overloads list are unique
namespace static_check{
template<bool>
struct check{inline check(){}};
template<>
struct check<false>;
};
#define STATIC_CHECK(expr,msg)
static_check::check<expr>(ERROR_##msg);
// Helper function used to check if all types in the sequence are
unique
template<class l>
struct is_unique : boost::mpl::and_<
boost::mpl::not_<
boost::mpl::contains<
typename boost::mpl::pop_front<l>::type,
typename boost::mpl::front<l>::type
>
>,
is_unique<
typename boost::mpl::pop_front<l>::type
>
>
{};
template<>
struct is_unique<boost::mpl::l_end> : boost::mpl::true_
{};
// Just a helper used to get result type both from binded functors
and functions
template<class is_function,class T>
struct get_result_type_impl
{
typedef typename boost::function_traits<typename
boost::remove_pointer<T>::type>::result_type result_type;
};
template<class T>
struct get_result_type_impl<boost::mpl::false_,T>
{
typedef typename T::result_type result_type;
};
template<class T>
struct get_result_type
{
typedef typename get_result_type_impl<
typename boost::mpl::and_<
boost::is_pointer<T>,
boost::is_function<typename boost::remove_pointer<T>::type>
>::type,
T
>::result_type result_type;
};
// Trick kernel, provides type cast function for each type in the
list
template<class type,class l>
struct proxy_impl : proxy_impl<
typename boost::mpl::front<l>::type,
typename boost::mpl::pop_front<l>::type>
{
typedef proxy_impl<
typename boost::mpl::front<l>::type,
typename boost::mpl::pop_front<l>::type> base;
proxy_impl(type t,const base& b)
:t_(t),base(b)
{}
operator typename get_result_type<type>::result_type()const
{
return t_();
}
private:
const type t_;
};
template<class type>
struct proxy_impl<type,boost::mpl::l_end>
{
proxy_impl(type t)
:t_(t)
{}
operator typename get_result_type<type>::result_type()const
{
return t_();
}
private:
const type t_;
};
template<class l>
struct proxy : proxy_impl<
typename boost::mpl::front<l>::type,
typename boost::mpl::pop_front<l>::type>
{
STATIC_CHECK(is_unique<l>::value,each_return_type_in_the_functions_list_mus t_be_unique)
typedef proxy_impl<
typename boost::mpl::front<l>::type,
typename boost::mpl::pop_front<l>::type
> base;
};
}
// Basic variant, only one type cast provided
template<class T0>
typename proxy<boost::mpl::list<T0> >::base f(T0 t0)
{
return proxy<boost::mpl::list<T0> >::base(t0);
}
// Generate code for possible overloads
#define RETTYPE_generate(z,n,unused) \
template<BOOST_PP_ENUM_PARAMS(n,class T)> \
typename proxy< \
boost::mpl::list<BOOST_PP_ENUM_PARAMS(n,T)> \
>::base \
f(BOOST_PP_ENUM_BINARY_PARAMS(n,T,t)) \
{ \
return typename proxy< \
boost::mpl::list<BOOST_PP_ENUM_PARAMS(n,T)> \
>::base(t0,f(BOOST_PP_ENUM_SHIFTED_PARAMS(n,t))); \
}
BOOST_PP_REPEAT_FROM_TO(2,RETTYPE_OVERLOAD_MAX_COUNT,RETTYPE_generate,~)
#undef RETTYPE_generate
If somebody have anything to add concerning code quality or there is a
bug in this code, please, let me know.
----
Cheers,
Dmitry,
Mera Networks (http://meranetworks.com/)
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]