#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/include/joint_view.hpp>
#include <boost/fusion/include/single_view.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/transform.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;
namespace fusion = boost::fusion;
using proto::_;
template<class L,class R>
struct pick_left
{
BOOST_MPL_ASSERT((boost::is_same<L, R>));
typedef L type;
};
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
#define FutureGroup(x) proto::call<FutureGroup(x)>
#endif
struct FutureGroup
: proto::or_<
proto::when<
proto::terminal<_>
, fusion::single_view<proto::_value>(proto::_value)
>
, proto::when<
proto::logical_and<FutureGroup, FutureGroup>
, fusion::joint_view<
boost::add_const<FutureGroup(proto::_left) >
, boost::add_const<FutureGroup(proto::_right) >
>(FutureGroup(proto::_left), FutureGroup(proto::_right))
>
, proto::when<
proto::logical_or<FutureGroup, FutureGroup>
, pick_left<
FutureGroup(proto::_left)
, FutureGroup(proto::_right)
>(FutureGroup(proto::_left))
>
>
{};
#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
#undef FutureGroup
#endif
template<class E>
struct future_expr;
struct future_dom
: proto::domain<proto::generator<future_expr>, FutureGroup>
{};
template<class E>
struct future_expr
: proto::extends<E, future_expr<E>, future_dom>
{
explicit future_expr(E const &e)
: future_expr::proto_extends(e)
{}
typename fusion::result_of::as_vector<
typename boost::result_of<FutureGroup(E)>::type
>::type
get() const
{
return fusion::as_vector(FutureGroup()(*this));
}
};
template<class T>
struct future
: future_expr<typename proto::terminal<T>::type>
{
future(T const &t = T())
: future::proto_derived_expr(future::proto_base_expr::make(t))
{}
T get() const
{
return proto::value(*this);
}
};
struct A {};
struct B {};
struct C {};
int main()
{
using fusion::vector;
future<A> a;
future<B> b;
future<C> c;
future<vector<A,B> > ab;
A t0 = a.get();
vector<A, B, C> t1 = (a && b && c).get();
vector<A, C> t2 = ((a || a) && c).get();
vector<A, B, C> t3 = ((a && b || a && b) && c).get();
vector<vector<A, B>, C> t4 = ((ab || ab) && c).get();
return 0;
}