Commit 6660002d authored by neverlord's avatar neverlord

maintenance

parent 00f15911
...@@ -68,7 +68,8 @@ struct fsm_receiver : fsm_actor<fsm_receiver> ...@@ -68,7 +68,8 @@ struct fsm_receiver : fsm_actor<fsm_receiver>
void receiver(int64_t max) void receiver(int64_t max)
{ {
int64_t value; int64_t value;
receive_while([&]() { return value < max; }) receive_while(gref(value) < max)
//receive_while([&]() { return value < max; })
( (
on(atom("msg")) >> [&]() on(atom("msg")) >> [&]()
{ {
......
...@@ -362,16 +362,23 @@ template<class Pattern, typename Fun> ...@@ -362,16 +362,23 @@ template<class Pattern, typename Fun>
std::unique_ptr<invokable> get_invokable_impl(Fun&& fun, std::unique_ptr<invokable> get_invokable_impl(Fun&& fun,
std::unique_ptr<value_matcher>&& vm) std::unique_ptr<value_matcher>&& vm)
{ {
typedef typename select_invokable_impl<Fun, Pattern>::type result; typedef std::unique_ptr<invokable> result;
return std::unique_ptr<invokable>{ if (vm)
new result(std::forward<Fun>(fun), std::move(vm))}; {
typedef typename select_invokable_impl<Fun, Pattern>::type impl1;
return result{new impl1{std::forward<Fun>(fun), std::move(vm)}};
}
typedef typename Pattern::types pattern_types;
typedef typename select_invokable_impl<Fun, pattern_types>::type impl2;
return result{new impl2{std::forward<Fun>(fun)}};
} }
template<class Pattern, typename Fun> template<class Pattern, typename Fun>
std::unique_ptr<invokable> get_invokable_impl(Fun&& fun) std::unique_ptr<invokable> get_invokable_impl(Fun&& fun)
{ {
typedef typename select_invokable_impl<Fun, typename Pattern::types>::type result; typedef typename Pattern::types pattern_types;
return std::unique_ptr<invokable>{new result(std::forward<Fun>(fun))}; typedef typename select_invokable_impl<Fun, pattern_types>::type impl;
return std::unique_ptr<invokable>{new impl(std::forward<Fun>(fun))};
} }
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -104,6 +104,8 @@ struct tdata<> ...@@ -104,6 +104,8 @@ struct tdata<>
throw std::out_of_range(""); throw std::out_of_range("");
} }
inline void set() { }
inline bool operator==(tdata const&) const { return true; } inline bool operator==(tdata const&) const { return true; }
}; };
...@@ -160,6 +162,13 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -160,6 +162,13 @@ struct tdata<Head, Tail...> : tdata<Tail...>
return *this; return *this;
} }
template<typename Arg0, typename... Args>
inline void set(Arg0&& arg0, Args&&... args)
{
head = std::forward<Arg0>(arg0);
super::set(std::forward<Args>(args)...);
}
// upcast // upcast
inline tdata<Tail...>& tail() { return *this; } inline tdata<Tail...>& tail() { return *this; }
inline tdata<Tail...> const& tail() const { return *this; } inline tdata<Tail...> const& tail() const { return *this; }
...@@ -215,6 +224,13 @@ struct tdata<option<Head>, Tail...> : tdata<Tail...> ...@@ -215,6 +224,13 @@ struct tdata<option<Head>, Tail...> : tdata<Tail...>
{ {
} }
template<typename Arg0, typename... Args>
inline void set(Arg0&& arg0, Args&&... args)
{
head = std::forward<Arg0>(arg0);
super::set(std::forward<Args>(args)...);
}
template<typename... Y> template<typename... Y>
tdata& operator=(tdata<Y...> const& other) tdata& operator=(tdata<Y...> const& other)
{ {
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include <type_traits> #include <type_traits>
#include "cppa/util/at.hpp" #include "cppa/util/at.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/detail/tdata.hpp" #include "cppa/detail/tdata.hpp"
namespace cppa { namespace cppa {
...@@ -91,6 +93,10 @@ struct guard_expr ...@@ -91,6 +93,10 @@ struct guard_expr
guard_expr(guard_expr const&) = default; guard_expr(guard_expr const&) = default;
guard_expr(guard_expr&& other) : m_args(std::move(other.m_args)) { } guard_expr(guard_expr&& other) : m_args(std::move(other.m_args)) { }
template<typename... Args>
bool operator()(Args const&... args) const;
}; };
#define CPPA_FORALL_OPS(SubMacro) \ #define CPPA_FORALL_OPS(SubMacro) \
...@@ -295,6 +301,39 @@ struct guard_placeholder ...@@ -295,6 +301,39 @@ struct guard_placeholder
}; };
template<typename T>
struct ge_reference_wrapper
{
T const* value;
ge_reference_wrapper(T&&) = delete;
ge_reference_wrapper(T const& val_ref) : value(&val_ref) { }
ge_reference_wrapper(ge_reference_wrapper const&) = default;
ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default;
T const& get() const { return *value; }
operator T const& () const { return *value; }
};
// support use of gref(BooleanVariable) as receive loop 'guard'
template<>
struct ge_reference_wrapper<bool>
{
bool const* value;
ge_reference_wrapper(bool&&) = delete;
ge_reference_wrapper(bool const& val_ref) : value(&val_ref) { }
ge_reference_wrapper(ge_reference_wrapper const&) = default;
ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default;
bool get() const { return *value; }
operator bool () const { return *value; }
bool operator()() const { return *value; }
};
/**
* @brief Create a reference wrapper similar to std::reference_wrapper<const T>
* that could be used in guard expressions or to enforce lazy evaluation.
*/
template<typename T>
ge_reference_wrapper<T> gref(T const& value) { return {value}; }
// result type computation // result type computation
...@@ -304,6 +343,12 @@ struct ge_unbound ...@@ -304,6 +343,12 @@ struct ge_unbound
typedef T type; typedef T type;
}; };
template<typename T, class Tuple>
struct ge_unbound<ge_reference_wrapper<T>, Tuple>
{
typedef T type;
};
// unbound type of placeholder // unbound type of placeholder
template<int X, typename... Ts> template<int X, typename... Ts>
struct ge_unbound<guard_placeholder<X>, detail::tdata<Ts...> > struct ge_unbound<guard_placeholder<X>, detail::tdata<Ts...> >
...@@ -315,51 +360,49 @@ struct ge_unbound<guard_placeholder<X>, detail::tdata<Ts...> > ...@@ -315,51 +360,49 @@ struct ge_unbound<guard_placeholder<X>, detail::tdata<Ts...> >
// operators, operators, operators // operators, operators, operators
#define CPPA_GUARD_PLACEHOLDER_OPERATOR(EnumValue, Operator) \ template<typename T>
template<int Pos1, int Pos2> \ struct is_ge_type
guard_expr< EnumValue , guard_placeholder<Pos1>, guard_placeholder<Pos2>> \ {
operator Operator (guard_placeholder<Pos1> p1, guard_placeholder<Pos2> p2) \ static constexpr bool value = false;
{ return {p1, p2}; } \ };
template<int Pos, typename T> \
guard_expr< EnumValue , guard_placeholder<Pos>, \ template<int X>
typename detail::strip_and_convert<T>::type > \ struct is_ge_type<guard_placeholder<X> >
operator Operator (guard_placeholder<Pos> gp, T value) \ {
{ return {std::move(gp), std::move(value)}; } \ static constexpr bool value = true;
template<typename T, int Pos> \ };
guard_expr< EnumValue , \
typename detail::strip_and_convert<T>::type, \ template<typename T>
guard_placeholder<Pos> > \ struct is_ge_type<ge_reference_wrapper<T> >
operator Operator (T value, guard_placeholder<Pos> gp) \ {
{ return {std::move(value), std::move(gp)}; } static constexpr bool value = true;
};
CPPA_FORALL_OPS(CPPA_GUARD_PLACEHOLDER_OPERATOR)
template<operator_id OP, typename First, typename Second>
#define CPPA_GUARD_EXPR_OPERATOR(EnumValue, Operator) \ struct is_ge_type<guard_expr<OP, First, Second> >
template<operator_id OP, typename F, typename S, typename T> \ {
guard_expr< EnumValue , guard_expr<OP, F, S>, \ static constexpr bool value = true;
typename detail::strip_and_convert<T>::type> \ };
operator Operator (guard_expr<OP, F, S> lhs, T rhs) \
{ return {lhs, rhs}; } \ template<operator_id OP, typename T1, typename T2>
template<typename T, operator_id OP, typename F, typename S> \ guard_expr<OP, typename detail::strip_and_convert<T1>::type,
guard_expr< EnumValue , typename detail::strip_and_convert<T>::type, \ typename detail::strip_and_convert<T2>::type>
guard_expr<OP, F, S>> \ ge_concatenate(T1 first, T2 second,
operator Operator (T lhs, guard_expr<OP, F, S> rhs) \ typename util::enable_if_c<
{ return {lhs, rhs}; } \ is_ge_type<T1>::value || is_ge_type<T2>::value
template<operator_id OP, typename F, typename S, int X> \ >::type* = 0)
guard_expr< EnumValue , guard_expr<OP, F, S>, guard_placeholder<X> > \ {
operator Operator (guard_expr<OP, F, S> lhs, guard_placeholder<X> rhs) \ return {first, second};
{ return {lhs, rhs}; } \ }
template<int X, operator_id OP, typename F, typename S> \
guard_expr< EnumValue , guard_placeholder<X>, guard_expr<OP, F, S>> \ #define CPPA_GE_OPERATOR(EnumValue, Operator) \
operator Operator (guard_placeholder<X> lhs, guard_expr<OP, F, S> rhs) \ template<typename T1, typename T2> \
{ return {lhs, rhs}; } \ auto operator Operator (T1 v1, T2 v2) \
template<operator_id OP1, typename F1, typename S1, \ -> decltype(ge_concatenate< EnumValue >(v1, v2)) { \
operator_id OP2, typename F2, typename S2> \ return ge_concatenate< EnumValue >(v1, v2); \
guard_expr< EnumValue , guard_expr<OP1, F1, S1>, guard_expr<OP2, F2, S2>> \ }
operator Operator (guard_expr<OP1,F1,S1> lhs, guard_expr<OP2,F2,S2> rhs) \
{ return {lhs, rhs}; } CPPA_FORALL_OPS(CPPA_GE_OPERATOR)
CPPA_FORALL_OPS(CPPA_GUARD_EXPR_OPERATOR)
template<operator_id OP> template<operator_id OP>
struct ge_eval_op; struct ge_eval_op;
...@@ -430,25 +473,6 @@ struct ge_result_<guard_expr<exec_fun3_op, First, Second>, Tuple> ...@@ -430,25 +473,6 @@ struct ge_result_<guard_expr<exec_fun3_op, First, Second>, Tuple>
)) type; )) type;
}; };
/*
#define CPPA_G_RESULT_TYPE_SPECIALIZATION(EnumValue, Operator) \
template<typename First, typename Second, class Tuple> \
struct ge_result_< guard_expr< EnumValue , First, Second>, Tuple> \
{ \
typedef typename ge_result_<First, Tuple>::type lhs_type; \
typedef typename ge_result_<Second, Tuple>::type rhs_type; \
typedef decltype(*static_cast<lhs_type const*>(nullptr) \
Operator \
*static_cast<rhs_type const*>(nullptr)) type; \
};
CPPA_G_RESULT_TYPE_SPECIALIZATION(addition_op, +)
CPPA_G_RESULT_TYPE_SPECIALIZATION(subtraction_op, -)
CPPA_G_RESULT_TYPE_SPECIALIZATION(multiplication_op, *)
CPPA_G_RESULT_TYPE_SPECIALIZATION(division_op, /)
CPPA_G_RESULT_TYPE_SPECIALIZATION(modulo_op, %)
*/
template<operator_id OP, typename First, typename Second, class Tuple> template<operator_id OP, typename First, typename Second, class Tuple>
struct ge_result struct ge_result
{ {
...@@ -483,6 +507,12 @@ inline T const& ge_resolve(Tuple const&, T const& value) ...@@ -483,6 +507,12 @@ inline T const& ge_resolve(Tuple const&, T const& value)
return value; return value;
} }
template<class Tuple, typename T>
inline T const& ge_resolve(Tuple const&, ge_reference_wrapper<T> const& value)
{
return value.get();
}
template<class Tuple, int X> template<class Tuple, int X>
inline auto ge_resolve(Tuple const& tup, guard_placeholder<X>) inline auto ge_resolve(Tuple const& tup, guard_placeholder<X>)
-> decltype(*get<X>(tup)) -> decltype(*get<X>(tup))
...@@ -635,6 +665,15 @@ ge_invoke_any(guard_expr<OP, First, Second> const& ge, ...@@ -635,6 +665,15 @@ ge_invoke_any(guard_expr<OP, First, Second> const& ge,
return util::unchecked_apply_tuple<result_type>(f, *x); return util::unchecked_apply_tuple<result_type>(f, *x);
} }
template<operator_id OP, typename First, typename Second>
template<typename... Args>
bool guard_expr<OP, First, Second>::operator()(Args const&... args) const
{
static_assert(std::is_same<decltype(ge_invoke(*this, args...)), bool>::value,
"guard expression does not return a boolean");
return ge_invoke(*this, args...);
}
// finally ... // finally ...
namespace placeholders { namespace { namespace placeholders { namespace {
......
...@@ -126,27 +126,59 @@ class rvalue_builder ...@@ -126,27 +126,59 @@ class rvalue_builder
public: public:
template<operator_id OP, typename F, typename S> //template<operator_id OP, typename F, typename S>
rvalue_builder& when(guard_expr<OP, F, S> ge) //rvalue_builder& when(guard_expr<OP, F, S> ge)
template<typename Fun>
rvalue_builder& when(Fun&& fun)
{ {
typedef guard_expr<OP, F, S> gtype; //TODO: static_assert
struct vm_impl : value_matcher typedef typename util::rm_ref<Fun>::type fun_type;
if (m_vm)
{ {
vm_ptr m_ptr; struct impl1 : value_matcher
gtype m_ge;
vm_impl(vm_ptr&& ptr, gtype&& g) : m_ptr(std::move(ptr)), m_ge(std::move(g)) { }
bool operator()(any_tuple const& tup) const
{ {
static_assert(std::is_same<decltype(ge_invoke_any<types>(m_ge, tup)), bool>::value, vm_ptr m_ptr;
"guard expression does not return a boolean"); fun_type m_fun;
if ((*m_ptr)(tup)) impl1(vm_ptr&& ptr, Fun&& f)
: m_ptr(std::move(ptr)), m_fun(std::forward<Fun>(f))
{ {
return ge_invoke_any<types>(m_ge, tup);
} }
return false; bool operator()(any_tuple const& tup) const
} {
}; if ((*m_ptr)(tup))
m_vm.reset(new vm_impl(std::move(m_vm), std::move(ge))); {
auto ttup = tuple_cast(tup, types{});
if (ttup)
{
return util::unchecked_apply_tuple<bool>(m_fun,
*ttup);
}
}
return false;
}
};
m_vm.reset(new impl1{std::move(m_vm), std::forward<Fun>(fun)});
}
else
{
struct impl2 : value_matcher
{
fun_type m_fun;
impl2(Fun&& f) : m_fun(std::forward<Fun>(f))
{
}
bool operator()(any_tuple const& tup) const
{
auto ttup = tuple_cast(tup, types{});
if (ttup)
{
return util::unchecked_apply_tuple<bool>(m_fun, *ttup);
}
return false;
}
};
m_vm.reset(new impl2{std::forward<Fun>(fun)});
}
return *this; return *this;
} }
......
...@@ -313,11 +313,14 @@ class pattern ...@@ -313,11 +313,14 @@ class pattern
m_vm.reset(new value_matcher_impl<wildcard_pos, types, util::type_list<Args...> >{data}); m_vm.reset(new value_matcher_impl<wildcard_pos, types, util::type_list<Args...> >{data});
} }
pattern(std::unique_ptr<value_matcher>&& vm) : m_vm(std::move(vm)) { } pattern(std::unique_ptr<value_matcher>&& vm) : m_vm(std::move(vm))
{
if (!m_vm) m_vm.reset(new dummy_matcher);
}
static inline value_matcher* get_value_matcher() static inline value_matcher* get_value_matcher()
{ {
return new dummy_matcher; return nullptr;
} }
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
......
...@@ -97,6 +97,8 @@ struct get_callable_trait ...@@ -97,6 +97,8 @@ struct get_callable_trait
std::is_member_function_pointer<fun_type>::value, std::is_member_function_pointer<fun_type>::value,
fun_type>::type fun_type>::type
type; type;
typedef typename type::result_type result_type;
typedef typename type::arg_types arg_types;
}; };
template<typename C> template<typename C>
......
...@@ -58,7 +58,7 @@ int main(int, char**) ...@@ -58,7 +58,7 @@ int main(int, char**)
// receive two messages // receive two messages
int i = 0; int i = 0;
receive_while([&]() { return ++i <= 2; }) receive_for(i, 2)
( (
// note: we sent a foo_pair2, but match on foo_pair // note: we sent a foo_pair2, but match on foo_pair
// that's safe because both are aliases for std::pair<int,int> // that's safe because both are aliases for std::pair<int,int>
......
...@@ -116,7 +116,7 @@ int main(int, char**) ...@@ -116,7 +116,7 @@ int main(int, char**)
// receive two messages // receive two messages
int i = 0; int i = 0;
receive_while([&]() { return ++i <= 2; }) receive_for(i, 2)
( (
on<bar>() >> [](bar const& val) on<bar>() >> [](bar const& val)
{ {
......
...@@ -200,7 +200,7 @@ int main() ...@@ -200,7 +200,7 @@ int main()
// receive both messages // receive both messages
int i = 0; int i = 0;
receive_while([&]() { return ++i <= 2; }) receive_for(i, 2)
( (
// ... and receive it // ... and receive it
on<tree>() >> [](const tree& tmsg) on<tree>() >> [](const tree& tmsg)
......
...@@ -33,7 +33,8 @@ void math_fun() ...@@ -33,7 +33,8 @@ void math_fun()
done = true; done = true;
} }
) )
.until([&]() { return done; }); .until(gref(done));
//.until([&]() { return done; });
} }
struct math_actor : event_based_actor struct math_actor : event_based_actor
......
...@@ -41,7 +41,6 @@ size_t test__local_group() ...@@ -41,7 +41,6 @@ size_t test__local_group()
} }
send(foo_group, 2); send(foo_group, 2);
int result = 0; int result = 0;
//receive_until([&result]() { return result == 10; })
do_receive do_receive
( (
on<int>() >> [&](int value) on<int>() >> [&](int value)
...@@ -55,7 +54,7 @@ size_t test__local_group() ...@@ -55,7 +54,7 @@ size_t test__local_group()
result = 10; result = 10;
} }
) )
.until([&result]() { return result == 10; }); .until(gref(result) == 10);
await_all_others_done(); await_all_others_done();
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
...@@ -48,9 +48,10 @@ size_t test__match() ...@@ -48,9 +48,10 @@ size_t test__match()
auto expr2 = _x1 + _x2 < _x3; auto expr2 = _x1 + _x2 < _x3;
auto expr3 = _x1 % _x2 == 0; auto expr3 = _x1 % _x2 == 0;
CPPA_CHECK_EQUAL(5, (ge_invoke(expr1, 2, 3))); CPPA_CHECK_EQUAL(5, (ge_invoke(expr1, 2, 3)));
CPPA_CHECK(ge_invoke(expr2, 1, 2, 4)); //CPPA_CHECK(ge_invoke(expr2, 1, 2, 4));
CPPA_CHECK(expr2(1, 2, 4));
CPPA_CHECK_EQUAL("12", (ge_invoke(expr1, std::string{"1"}, std::string{"2"}))); CPPA_CHECK_EQUAL("12", (ge_invoke(expr1, std::string{"1"}, std::string{"2"})));
CPPA_CHECK((ge_invoke(expr3, 100, 2))); CPPA_CHECK(expr3(100, 2));
auto expr4 = _x1 == "-h" || _x1 == "--help"; auto expr4 = _x1 == "-h" || _x1 == "--help";
CPPA_CHECK(ge_invoke(expr4, string("-h"))); CPPA_CHECK(ge_invoke(expr4, string("-h")));
......
...@@ -212,7 +212,7 @@ class testee_actor : public scheduled_actor ...@@ -212,7 +212,7 @@ class testee_actor : public scheduled_actor
reply("wait4string"); reply("wait4string");
} }
) )
.until([&]() { return string_received; }); .until(gref(string_received));
} }
void wait4float() void wait4float()
...@@ -230,7 +230,7 @@ class testee_actor : public scheduled_actor ...@@ -230,7 +230,7 @@ class testee_actor : public scheduled_actor
reply("wait4float"); reply("wait4float");
} }
) )
.until([&]() { return float_received; }); .until(gref(float_received));
} }
public: public:
...@@ -281,11 +281,11 @@ void testee3(actor_ptr parent) ...@@ -281,11 +281,11 @@ void testee3(actor_ptr parent)
// test a future_send / delayed_reply based loop // test a future_send / delayed_reply based loop
future_send(self, std::chrono::milliseconds(50), atom("Poll")); future_send(self, std::chrono::milliseconds(50), atom("Poll"));
int polls = 0; int polls = 0;
receive_while([&polls]() { return ++polls <= 5; }) receive_for(polls, 5)
( (
on(atom("Poll")) >> [&]() on(atom("Poll")) >> [&]()
{ {
if (polls < 5) if (polls < 4)
{ {
delayed_reply(std::chrono::milliseconds(50), atom("Poll")); delayed_reply(std::chrono::milliseconds(50), atom("Poll"));
} }
...@@ -386,7 +386,7 @@ size_t test__spawn() ...@@ -386,7 +386,7 @@ size_t test__spawn()
int flags = 0; int flags = 0;
future_send(self, std::chrono::seconds(1), atom("FooBar")); future_send(self, std::chrono::seconds(1), atom("FooBar"));
// wait for :Down and :Exit messages of pong // wait for :Down and :Exit messages of pong
receive_while([&i]() { return ++i <= 3; }) receive_for(i, 3)
( (
on<atom(":Exit"), std::uint32_t>() >> [&](std::uint32_t reason) on<atom(":Exit"), std::uint32_t>() >> [&](std::uint32_t reason)
{ {
...@@ -424,26 +424,6 @@ size_t test__spawn() ...@@ -424,26 +424,6 @@ size_t test__spawn()
// verify pong messages // verify pong messages
CPPA_CHECK_EQUAL(pongs(), 5); CPPA_CHECK_EQUAL(pongs(), 5);
/*
spawn(testee3, self);
i = 0;
// testee3 sends 5 { "Push", int } messages in a 50 milliseconds interval;
// allow for a maximum error of 5ms
receive_while([&i]() { return ++i <= 5; })
(
on<atom("Push"), int>() >> [&](int val)
{
CPPA_CHECK_EQUAL(i, val);
//cout << "{ Push, " << val << " } ..." << endl;
},
after(std::chrono::milliseconds(55)) >> [&]()
{
cout << "Push " << i
<< " was delayed more than 55 milliseconds" << endl;
CPPA_CHECK(false);
}
);
*/
await_all_others_done(); await_all_others_done();
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
...@@ -25,9 +25,65 @@ using std::endl; ...@@ -25,9 +25,65 @@ using std::endl;
using namespace cppa; using namespace cppa;
template<class Expr, class Guard, typename Result, typename... Args>
class tpartial_function
{
public:
tpartial_function(Guard&& g, Expr&& e)
: m_guard(std::move(g)), m_expr(std::move(e))
{
}
tpartial_function(tpartial_function&&) = default;
tpartial_function(tpartial_function const&) = default;
bool defined_at(Args const&... args)
{
return m_guard(args...);
}
Result operator()(Args const&... args)
{
return m_expr(args...);
}
private:
detail::tdata<Args...> m_args;
Guard m_guard;
Expr m_expr;
};
template<class Expr, class Guard, typename Result, class ArgTypes>
struct tpf_;
template<class Expr, class Guard, typename Result, typename... Ts>
struct tpf_<Expr, Guard, Result, util::type_list<Ts...> >
{
typedef tpartial_function<Expr, Guard, Result, Ts...> type;
};
template<class Expr, class Guard>
typename tpf_<Expr, Guard,
typename util::get_callable_trait<Expr>::result_type,
typename util::get_callable_trait<Expr>::arg_types
>::type
tfun(Expr e, Guard g)
{
return {std::move(g), std::move(e)};
}
size_t test__tuple() size_t test__tuple()
{ {
CPPA_TEST(test__tuple); CPPA_TEST(test__tuple);
using namespace cppa::placeholders;
// check type correctness of make_cow_tuple() // check type correctness of make_cow_tuple()
auto t0 = make_cow_tuple("1", 2); auto t0 = make_cow_tuple("1", 2);
CPPA_CHECK((std::is_same<decltype(t0), cppa::cow_tuple<std::string, int>>::value)); CPPA_CHECK((std::is_same<decltype(t0), cppa::cow_tuple<std::string, int>>::value));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment