#include <iostream>
#include <boost/mpl/or.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
using namespace std;
namespace details
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
#define MAX_RESULT_ARITY 5
#define TEXT(z, n, text) text
#define BUILD_IMPL(z,n,text) \
template< class F \
, template<BOOST_PP_ENUM(n, TEXT, class)> \
class T = F::template result \
> struct BOOST_PP_CAT(has_result_impl_,n) \
{ typedef void type; }; \
template<class F, class EnableIf = void> \
struct BOOST_PP_CAT(has_result_,n) : boost::mpl::false_ {}; \
template<class F> \
struct BOOST_PP_CAT(has_result_,n)<F \
,typename BOOST_PP_CAT(has_result_impl_,n)<F>::type> \
: boost::mpl::true_ {}; \
/**/
BOOST_PP_REPEAT_FROM_TO(1,MAX_RESULT_ARITY,BUILD_IMPL,~)
}
#define B_OR(z,n,text) \
boost::mpl::or_< details::BOOST_PP_CAT(has_result_,n)<F>,\
#define E_OR(z,n,text) >
template<class F>
struct support_result_of_protocol
: BOOST_PP_REPEAT_FROM_TO(1,MAX_RESULT_ARITY,B_OR,~)
details::has_result_type<F>
BOOST_PP_REPEAT_FROM_TO(1,MAX_RESULT_ARITY,E_OR,~) ::type
{
};
struct nothing
{
};
struct has_a_result_type
{
typedef void result_type;
};
struct has_a_result
{
template<typename FArgs>
struct result;
template<typename T>
struct result<has_a_result(T)>
{
typedef T** type;
};
};
struct has_a_bigger_result
{
template<typename F,class A0,class A1,class A2>
struct result;
};
int main()
{
cout << support_result_of_protocol<nothing>::value << endl;
cout << support_result_of_protocol<has_a_result_type>::value << endl;
cout << support_result_of_protocol<has_a_result>::value << endl;
cout << support_result_of_protocol<has_a_bigger_result>::value << endl;
}