154 lines
5.1 KiB
C++
154 lines
5.1 KiB
C++
|
////////////////////////////////////////////////////////////////////////////
|
||
|
// lazy smart.hpp
|
||
|
//
|
||
|
// Build lazy functoid traits for Phoenix equivalents for FC++
|
||
|
//
|
||
|
// These are equivalents of the Boost FC++ functoid traits in smart.hpp
|
||
|
//
|
||
|
// I have copied the versions for zero, one, two and three arguments.
|
||
|
//
|
||
|
/*=============================================================================
|
||
|
Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
|
||
|
Copyright (c) 2001-2007 Joel de Guzman
|
||
|
Copyright (c) 2015 John Fletcher
|
||
|
|
||
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||
|
==============================================================================*/
|
||
|
|
||
|
#ifndef BOOST_PHOENIX_FUNCTION_LAZY_SMART
|
||
|
#define BOOST_PHOENIX_FUNCTION_LAZY_SMART
|
||
|
|
||
|
namespace boost {
|
||
|
namespace phoenix {
|
||
|
namespace fcpp {
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
// Feature: Smartness
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
// If F is smart, then we can refer to these entities:
|
||
|
//
|
||
|
// functoid_traits<F>::template accepts<N>::args
|
||
|
// A bool which says whether F can accept N arguments
|
||
|
//
|
||
|
// functoid_traits<F>::max_args
|
||
|
// An int which says what the most arguments F can accept is
|
||
|
//
|
||
|
// functoid_traits<F>::template ensure_accepts<N>::args()
|
||
|
// A no-op call that compiles only if F can accept N args
|
||
|
//
|
||
|
// We use traits so that if you happen to ask a non-smart functoid these
|
||
|
// questions, you will hopefully get a literate error message.
|
||
|
|
||
|
struct SmartFunctoid {};
|
||
|
|
||
|
// We add crazy identifiers to ensure that users don't accidentally talk
|
||
|
// to functoids directly; they should always be going through the traits
|
||
|
// class to ask for info.
|
||
|
struct smart_functoid0 : public SmartFunctoid {
|
||
|
template <class Dummy, int i> struct crazy_accepts {
|
||
|
static const bool args = false;
|
||
|
};
|
||
|
template <class Dummy> struct crazy_accepts<Dummy,0> {
|
||
|
static const bool args = true;
|
||
|
};
|
||
|
static const int crazy_max_args = 0;
|
||
|
};
|
||
|
|
||
|
struct smart_functoid1 : public SmartFunctoid {
|
||
|
template <class Dummy, int i> struct crazy_accepts {
|
||
|
static const bool args = false;
|
||
|
};
|
||
|
template <class Dummy> struct crazy_accepts<Dummy,1> {
|
||
|
static const bool args = true;
|
||
|
};
|
||
|
static const int crazy_max_args = 1;
|
||
|
};
|
||
|
|
||
|
struct smart_functoid2 : public SmartFunctoid {
|
||
|
template <class Dummy, int i> struct crazy_accepts {
|
||
|
static const bool args = false;
|
||
|
};
|
||
|
template <class Dummy> struct crazy_accepts<Dummy,1> {
|
||
|
static const bool args = true;
|
||
|
};
|
||
|
template <class Dummy> struct crazy_accepts<Dummy,2> {
|
||
|
static const bool args = true;
|
||
|
};
|
||
|
static const int crazy_max_args = 2;
|
||
|
};
|
||
|
|
||
|
struct smart_functoid3 : public SmartFunctoid {
|
||
|
template <class Dummy, int i> struct crazy_accepts {
|
||
|
static const bool args = false;
|
||
|
};
|
||
|
template <class Dummy> struct crazy_accepts<Dummy,1> {
|
||
|
static const bool args = true;
|
||
|
};
|
||
|
template <class Dummy> struct crazy_accepts<Dummy,2> {
|
||
|
static const bool args = true;
|
||
|
};
|
||
|
template <class Dummy> struct crazy_accepts<Dummy,3> {
|
||
|
static const bool args = true;
|
||
|
};
|
||
|
static const int crazy_max_args = 3;
|
||
|
};
|
||
|
|
||
|
|
||
|
namespace impl {
|
||
|
template <class F, bool b> struct NeededASmartFunctoidButInsteadGot {};
|
||
|
template <class F> struct NeededASmartFunctoidButInsteadGot<F,true> {
|
||
|
typedef F type;
|
||
|
};
|
||
|
template <bool b> struct Ensure;
|
||
|
template <> struct Ensure<true> {};
|
||
|
} // end namespace impl
|
||
|
|
||
|
template <class MaybeASmartFunctoid>
|
||
|
struct functoid_traits {
|
||
|
typedef typename boost::remove_reference<MaybeASmartFunctoid>::type MaybeASmartFunctoidT;
|
||
|
typedef
|
||
|
typename impl::NeededASmartFunctoidButInsteadGot<MaybeASmartFunctoidT,
|
||
|
boost::is_base_and_derived<SmartFunctoid,
|
||
|
MaybeASmartFunctoidT>::value>::type F;
|
||
|
template <int i> struct accepts {
|
||
|
static const bool args = F::template crazy_accepts<int,i>::args;
|
||
|
};
|
||
|
template <int i> struct ensure_accepts {
|
||
|
static const bool ok = F::template crazy_accepts<int,i>::args;
|
||
|
inline static void args() { (void) impl::Ensure<ok>(); }
|
||
|
};
|
||
|
static const int max_args = F::crazy_max_args;
|
||
|
};
|
||
|
|
||
|
// These can be used to make functoids smart without having to alter
|
||
|
// code elsewhere. These are used instead of boost::phoenix::function
|
||
|
// to declare the object.
|
||
|
template <typename F>
|
||
|
struct smart_function0 : public smart_functoid0,
|
||
|
public boost::phoenix::function<F>
|
||
|
{ };
|
||
|
|
||
|
template <typename F>
|
||
|
struct smart_function1 : public smart_functoid1,
|
||
|
public boost::phoenix::function<F>
|
||
|
{
|
||
|
typedef F type;
|
||
|
};
|
||
|
|
||
|
template <typename F>
|
||
|
struct smart_function2 : public smart_functoid2,
|
||
|
public boost::phoenix::function<F>
|
||
|
{ };
|
||
|
|
||
|
template <typename F>
|
||
|
struct smart_function3 : public smart_functoid3,
|
||
|
public boost::phoenix::function<F>
|
||
|
{ };
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#endif
|