Commit 49851bd0 authored by Dominik Charousset's avatar Dominik Charousset

`optional_variant<...>` => `variant<none_t, ...>`

This patch removes the weird `optional_variant` class from libcppa in favor of
a more general `variant` implementation that simply uses a `none_t` to indicate
a non-existing value.
parent bea4b168
......@@ -39,7 +39,6 @@
#include "cppa/to_string.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/cow_tuple.hpp"
#include "cppa/tuple_cast.hpp"
#include "cppa/singletons.hpp"
#include "cppa/typed_actor.hpp"
#include "cppa/exit_reason.hpp"
......
......@@ -21,11 +21,12 @@
#define CPPA_DETAIL_BEHAVIOR_IMPL_HPP
#include "cppa/atom.hpp"
#include "cppa/variant.hpp"
#include "cppa/optional.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/ref_counted.hpp"
#include "cppa/skip_message.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/optional_variant.hpp"
#include "cppa/timeout_definition.hpp"
#include "cppa/util/duration.hpp"
......@@ -47,9 +48,14 @@ template<class T> struct is_message_id_wrapper {
static constexpr bool value = sizeof(test<T>(0)) == 1;
};
struct optional_any_tuple_visitor {
inline bhvr_invoke_result operator()() const { return any_tuple{}; }
struct optional_any_tuple_visitor : static_visitor<bhvr_invoke_result> {
//inline bhvr_invoke_result operator()() const { return any_tuple{}; }
inline bhvr_invoke_result operator()(none_t&) const { return none; }
inline bhvr_invoke_result operator()(const none_t&) const { return none; }
inline bhvr_invoke_result operator()(skip_message_t&) const { return none; }
inline bhvr_invoke_result operator()(const skip_message_t&) const { return none; }
inline bhvr_invoke_result operator()(unit_t&) const { return any_tuple{}; }
inline bhvr_invoke_result operator()(const unit_t&) const { return any_tuple{}; }
template<typename T>
inline bhvr_invoke_result operator()(T& value, typename std::enable_if<not is_message_id_wrapper<T>::value>::type* = 0) const {
return make_any_tuple(std::move(value));
......@@ -137,9 +143,9 @@ class behavior_impl : public ref_counted {
};
struct dummy_match_expr {
inline optional_variant<void> invoke(const any_tuple&) const { return none; }
inline variant<none_t> invoke(const any_tuple&) const { return none; }
inline bool can_invoke(const any_tuple&) const { return false; }
inline optional_variant<void> operator()(const any_tuple&) const { return none; }
inline variant<none_t> operator()(const any_tuple&) const { return none; }
};
template<class MatchExpr, typename F>
......@@ -158,11 +164,13 @@ class default_behavior_impl : public behavior_impl {
: super(tout), m_expr(std::forward<Expr>(expr)), m_fun(f) { }
bhvr_invoke_result invoke(any_tuple& tup) {
return eval_res(m_expr(tup));
auto res = m_expr(tup);
return apply_visitor(optional_any_tuple_visitor{}, res);
}
bhvr_invoke_result invoke(const any_tuple& tup) {
return eval_res(m_expr(tup));
auto res = m_expr(tup);
return apply_visitor(optional_any_tuple_visitor{}, res);
}
bool defined_at(const any_tuple& tup) {
......@@ -177,24 +185,6 @@ class default_behavior_impl : public behavior_impl {
private:
template<typename... Ts>
typename std::enable_if<has_skip_message<Ts...>::value, bhvr_invoke_result>::type
eval_res(optional_variant<Ts...>&& res) {
if (res) {
if (res.template is<skip_message_t>()) {
return none;
}
return apply_visitor(optional_any_tuple_visitor{}, res);
}
return none;
}
template<typename... Ts>
typename std::enable_if<!has_skip_message<Ts...>::value, bhvr_invoke_result>::type
eval_res(optional_variant<Ts...>&& res) {
return apply_visitor(optional_any_tuple_visitor{}, res);
}
MatchExpr m_expr;
F m_fun;
......
......@@ -17,68 +17,57 @@
\******************************************************************************/
#ifndef CPPA_DETAIL_OPTIONAL_VARIANT_DATA
#define CPPA_DETAIL_OPTIONAL_VARIANT_DATA
#ifndef CPPA_DETAIL_VARIANT_DATA_HPP
#define CPPA_DETAIL_VARIANT_DATA_HPP
#include <stdexcept>
#include <type_traits>
#include "cppa/unit.hpp"
#include "cppa/none.hpp"
#include "cppa/lift_void.hpp"
#define CPPA_OPTIONAL_VARIANT_DATA_CONCAT(x, y) x ## y
#define CPPA_VARIANT_DATA_CONCAT(x, y) x ## y
#define CPPA_OPTIONAL_VARIANT_DATA_GETTER(pos) \
inline CPPA_OPTIONAL_VARIANT_DATA_CONCAT(T, pos) & \
#define CPPA_VARIANT_DATA_GETTER(pos) \
inline CPPA_VARIANT_DATA_CONCAT(T, pos) & \
get(std::integral_constant<int, pos >) { \
return CPPA_OPTIONAL_VARIANT_DATA_CONCAT(v, pos) ; \
return CPPA_VARIANT_DATA_CONCAT(v, pos) ; \
} \
inline const CPPA_OPTIONAL_VARIANT_DATA_CONCAT(T, pos) & \
inline const CPPA_VARIANT_DATA_CONCAT(T, pos) & \
get(std::integral_constant<int, pos >) const { \
return CPPA_OPTIONAL_VARIANT_DATA_CONCAT(v, pos) ; \
return CPPA_VARIANT_DATA_CONCAT(v, pos) ; \
}
namespace cppa {
namespace detail {
template<typename T>
struct lift_void { typedef T type; };
template<>
struct lift_void<void> { typedef unit_t type; };
template<typename T>
struct unlift_void { typedef T type; };
template<>
struct unlift_void<unit_t> { typedef void type; };
template<typename T0, typename T1 = unit_t,
typename T2 = unit_t, typename T3 = unit_t,
typename T4 = unit_t, typename T5 = unit_t,
typename T6 = unit_t, typename T7 = unit_t,
typename T8 = unit_t, typename T9 = unit_t>
struct optional_variant_data {
struct variant_data {
union {
T0 v0; T1 v1; T2 v2; T3 v3; T4 v4;
T5 v5; T6 v6; T7 v7; T8 v8; T9 v9;
};
optional_variant_data() { }
variant_data() { }
~optional_variant_data() { }
~variant_data() { }
CPPA_OPTIONAL_VARIANT_DATA_GETTER(0)
CPPA_OPTIONAL_VARIANT_DATA_GETTER(1)
CPPA_OPTIONAL_VARIANT_DATA_GETTER(2)
CPPA_OPTIONAL_VARIANT_DATA_GETTER(3)
CPPA_OPTIONAL_VARIANT_DATA_GETTER(4)
CPPA_OPTIONAL_VARIANT_DATA_GETTER(5)
CPPA_OPTIONAL_VARIANT_DATA_GETTER(6)
CPPA_OPTIONAL_VARIANT_DATA_GETTER(7)
CPPA_OPTIONAL_VARIANT_DATA_GETTER(8)
CPPA_OPTIONAL_VARIANT_DATA_GETTER(9)
CPPA_VARIANT_DATA_GETTER(0)
CPPA_VARIANT_DATA_GETTER(1)
CPPA_VARIANT_DATA_GETTER(2)
CPPA_VARIANT_DATA_GETTER(3)
CPPA_VARIANT_DATA_GETTER(4)
CPPA_VARIANT_DATA_GETTER(5)
CPPA_VARIANT_DATA_GETTER(6)
CPPA_VARIANT_DATA_GETTER(7)
CPPA_VARIANT_DATA_GETTER(8)
CPPA_VARIANT_DATA_GETTER(9)
private:
......@@ -89,7 +78,7 @@ struct optional_variant_data {
};
struct optional_variant_data_destructor {
struct variant_data_destructor {
inline void operator()() const { }
inline void operator()(const none_t&) const { }
template<typename T>
......@@ -99,4 +88,4 @@ struct optional_variant_data_destructor {
} // namespace detail
} // namespace cppa
#endif // CPPA_DETAIL_OPTIONAL_VARIANT_DATA
#endif // CPPA_DETAIL_VARIANT_DATA_HPP
......@@ -658,28 +658,6 @@ struct ge_invoke_helper {
}
};
template<typename TupleTypes, operator_id OP, typename First, typename Second>
typename ge_result<
OP, First, Second,
typename detail::tdata_from_type_list<
typename util::tl_filter_not<TupleTypes, is_anything>::type
>::type
>::type
ge_invoke_any(const guard_expr<OP, First, Second>& ge,
const any_tuple& tup) {
using namespace util;
typename std::conditional<
std::is_same<typename TupleTypes::back, anything>::value,
TupleTypes,
wrapped<typename tl_push_back<TupleTypes, anything>::type>
>::type
cast_token;
auto x = tuple_cast(tup, cast_token);
CPPA_REQUIRE(static_cast<bool>(x) == true);
ge_invoke_helper<guard_expr<OP, First, Second> > f{ge};
return util::apply_args(f, *x, util::get_indices(*x));
}
template<operator_id OP, typename First, typename Second>
template<typename... Ts>
bool guard_expr<OP, First, Second>::operator()(const Ts&... args) const {
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011 - 2014 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the Boost Software License, Version 1.0. See *
* accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt *
\******************************************************************************/
#ifndef CPPA_LIFT_VOID_HPP
#define CPPA_LIFT_VOID_HPP
#include "cppa/unit.hpp"
namespace cppa {
template<typename T>
struct lift_void {
using type = T;
};
template<>
struct lift_void<void> {
using type = unit_t;
};
template<typename T>
struct unlift_void {
using type = T;
};
template<>
struct unlift_void<unit_t> {
using type = void;
};
} // namespace cppa
#endif // CPPA_LIFT_VOID_HPP
......@@ -87,7 +87,7 @@ class match_each_helper {
auto expr = match_expr_collect(std::forward<Ts>(args)...);
for (; i != e; ++i) {
auto res = expr(p(*i));
if (!res) return i;
if (get<none_t>(&res)) return i;
}
return e;
}
......
......@@ -20,9 +20,11 @@
#ifndef CPPA_MATCH_EXPR_HPP
#define CPPA_MATCH_EXPR_HPP
#include "cppa/unit.hpp"
#include "cppa/variant.hpp"
#include "cppa/optional.hpp"
#include "cppa/lift_void.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/optional_variant.hpp"
#include "cppa/tpartial_function.hpp"
#include "cppa/util/call.hpp"
......@@ -471,6 +473,26 @@ struct has_bool_result {
typedef std::integral_constant<bool, value> token_type;
};
template<typename T>
inline bool unroll_expr_result_valid(const T&) {
return true;
}
template<typename T>
inline bool unroll_expr_result_valid(const optional<T>& opt) {
return static_cast<bool>(opt);
}
template<typename T>
inline T& unroll_expr_result_unbox(T& value) {
return value;
}
template<typename T>
inline T& unroll_expr_result_unbox(optional<T>& opt) {
return *opt;
}
template<typename Result, class PPFPs, typename PtrType, class Tuple>
Result unroll_expr(PPFPs&, std::uint64_t, minus1l, const std::type_info&,
bool, PtrType*, Tuple&) {
......@@ -488,7 +510,7 @@ Result unroll_expr(PPFPs& fs,
/* recursively evaluate sub expressions */ {
Result res = unroll_expr<Result>(fs, bitmask, long_constant<N-1>{},
type_token, is_dynamic, ptr, tup);
if (res) return res;
if (!get<none_t>(&res)) return res;
}
if ((bitmask & (0x01 << N)) == 0) return none;
auto& f = get<N>(fs);
......@@ -498,10 +520,13 @@ Result unroll_expr(PPFPs& fs,
typename policy::tuple_type targs;
if (policy::prepare_invoke(targs, type_token, is_dynamic, ptr, tup)) {
auto is = util::get_indices(targs);
return util::apply_args_prefixed(f.first,
deduce_const(tup, targs),
is,
f.second);
auto res = util::apply_args_prefixed(f.first,
deduce_const(tup, targs),
is,
f.second);
if (unroll_expr_result_valid(res)) {
return std::move(unroll_expr_result_unbox(res));
}
}
return none;
}
......@@ -616,6 +641,14 @@ struct get_case_result {
namespace cppa {
template<class List>
struct match_result_from_type_list;
template<typename... Ts>
struct match_result_from_type_list<util::type_list<Ts...>> {
typedef variant<none_t, typename lift_void<Ts>::type...> type;
};
/**
* @brief A match expression encapsulating cases <tt>Cs...</tt>, whereas
* each case is a @p detail::projection_partial_function_pair.
......@@ -629,7 +662,7 @@ class match_expr {
typedef util::type_list<Cs...> cases_list;
typedef typename optional_variant_from_type_list<
typedef typename match_result_from_type_list<
typename util::tl_distinct<
typename util::tl_map<
cases_list,
......
......@@ -26,6 +26,7 @@
#include "cppa/none.hpp"
#include "cppa/unit.hpp"
#include "cppa/optional.hpp"
#include "cppa/lift_void.hpp"
#include "cppa/util/call.hpp"
#include "cppa/util/type_list.hpp"
......@@ -41,21 +42,29 @@ struct tpartial_function_helper {
if (fun.defined_at(args...)) return fun.invoke(args...);
return none;
}
template<class Expr, class Tuple, class Indices>
inline Result lifted_result(Expr& expr, Tuple& tup, Indices& indices) {
return util::apply_args(expr, tup, indices);
}
};
template<typename... Ts>
struct tpartial_function_helper<void, Ts...> {
struct tpartial_function_helper<unit_t, Ts...> {
template<typename Fun>
inline optional<void> operator()(const Fun& fun, Ts... args) {
inline optional<unit_t> operator()(const Fun& fun, Ts... args) {
if (fun.defined_at(args...)) {
fun.invoke(args...);
return unit;
}
return none;
}
template<class Expr, class Tuple, class Indices>
inline unit_t lifted_result(Expr& expr, Tuple& tup, Indices& indices) {
util::apply_args(expr, tup, indices);
return unit;
}
};
template<class Expr, class Guard, typename Result, typename... Ts>
class tpartial_function {
......@@ -80,7 +89,7 @@ class tpartial_function {
static constexpr bool manipulates_args =
util::tl_exists<arg_types, util::is_mutable_ref>::value;
typedef Result result_type;
typedef typename lift_void<Result>::type result_type;
template<typename Fun, typename... G>
tpartial_function(Fun&& fun, G&&... guard_args)
......@@ -105,7 +114,8 @@ class tpartial_function {
result_type invoke(Ts... args) const {
auto targs = std::forward_as_tuple(args...);
auto indices = util::get_right_indices<num_expr_args>(targs);
return util::apply_args(m_expr, targs, indices);
tpartial_function_helper<result_type, Ts...> helper;
return helper.lifted_result(m_expr, targs, indices);
}
inline optional<result_type> operator()(Ts... args) const {
......
......@@ -73,8 +73,11 @@ struct valid_input_predicate {
template<typename Expr>
struct inner {
typedef typename Expr::input_types input_types;
typedef typename unbox_typed_continue_helper<
typename Expr::output_types
typedef typename util::tl_map<
typename unbox_typed_continue_helper<
typename Expr::output_types
>::type,
unlift_void
>::type
output_types;
// get matching elements for input type
......
......@@ -25,6 +25,7 @@
#include <type_traits>
#include "cppa/cppa_fwd.hpp"
#include "cppa/optional.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/type_traits.hpp"
......
......@@ -12,7 +12,6 @@ endmacro()
add_unit_test(ripemd_160)
add_unit_test(atom)
add_unit_test(optional_variant)
add_unit_test(metaprogramming)
add_unit_test(intrusive_containers)
add_unit_test(serialization)
......
......@@ -142,8 +142,33 @@ inline void cppa_check_value(V1 v1,
CPPA_PRINT("passed"); \
} ((void) 0)
namespace cppa {
inline bool is_false_or_none(bool value) {
return !value;
}
template<typename... Ts>
inline bool is_false_or_none(const variant<none_t, Ts...>& res) {
return get<none_t>(&res) != nullptr;
}
template<typename T>
inline bool is_false_or_none(const optional<T>& res) {
return !static_cast<bool>(res);
}
} // namespace cppa
#define CPPA_CHECK(line_of_code) \
if (!(line_of_code)) { \
if (cppa::is_false_or_none(line_of_code)) { \
CPPA_PRINTERR(#line_of_code); \
cppa_inc_error_count(); \
} \
else { CPPA_PRINT("passed"); } CPPA_VOID_STMT
#define CPPA_CHECK_NOT(line_of_code) \
if (!cppa::is_false_or_none(line_of_code)) { \
CPPA_PRINTERR(#line_of_code); \
cppa_inc_error_count(); \
} \
......
......@@ -169,7 +169,7 @@ void test_gref() {
);
any_tuple expr19_tup = make_cow_tuple("hello guard!");
auto res19 = expr19(expr19_tup);
CPPA_CHECK(res19.is<int>() && get<int>(res19) == 2);
CPPA_CHECK(get<int>(&res19) && get<int>(res19) == 2);
partial_function expr20 = expr19;
enable_case1 = false;
CPPA_CHECK(expr20(expr19_tup) == make_any_tuple(1));
......@@ -188,32 +188,32 @@ void test_match_function() {
CPPA_CHECK_EQUAL(i, 5);
}
);
CPPA_CHECK(res0);
CPPA_CHECK(!get<none_t>(&res0));
auto res1 = match("value=42") (
on(kvp_split).when(_x1.not_empty()) >> [&](const vector<string>& vec) {
CPPA_CHECK_EQUAL("value", vec[0]);
CPPA_CHECK_EQUAL("42", vec[1]);
}
);
CPPA_CHECK(res1);
CPPA_CHECK(!get<none_t>(&res1));
auto res2 = match("42") (
on(toint) >> [&](int i) {
CPPA_CHECK_EQUAL(42, i);
}
);
CPPA_CHECK(res2);
CPPA_CHECK(!get<none_t>(&res2));
auto res3 = match("abc") (
on<string>().when(_x1 == "abc") >> [&] { }
);
CPPA_CHECK(res3);
CPPA_CHECK(res3.is<void>());
CPPA_CHECK(!get<none_t>(&res3));
CPPA_CHECK(get<unit_t>(&res3));
// match vectors
auto res4 = match(std::vector<int>{1, 2, 3}) (
on<int, int, int>().when( _x1 + _x2 + _x3 == 6
&& _x2(is_even)
&& _x3 % 2 == 1 ) >> [&] { }
);
CPPA_CHECK(res4);
CPPA_CHECK(!get<none_t>(&res4));
vector<string> vec{"a", "b", "c"};
auto res5 = match(vec) (
on("a", "b", val<string>) >> [](string&) -> string {
......@@ -342,7 +342,7 @@ void test_pattern_matching() {
return f;
}
);
CPPA_CHECK(res && res.is<float>() && util::safe_equal(get<float>(res), 4.2f));
CPPA_CHECK(get<float>(&res) && util::safe_equal(get<float>(res), 4.2f));
auto res2 = match(make_any_tuple(23, 4.2f)) (
on(42, arg_match) >> [](double d) {
return d;
......@@ -351,7 +351,7 @@ void test_pattern_matching() {
return f;
}
);
CPPA_CHECK(!res2);
CPPA_CHECK(get<none_t>(&res2));
}
inline void make_dynamically_typed_impl(detail::object_array&) { }
......@@ -377,7 +377,7 @@ void test_wildcards() {
CPPA_CHECK_EQUAL(b, 2);
}
);
CPPA_CHECK(not expr0(1));
CPPA_CHECK_NOT(expr0(1));
CPPA_CHECK(expr0(1, 2));
CPPA_CHECK(expr0(0, 1, 2));
partial_function pf0 = expr0;
......
#include <iostream>
#include <functional>
#include "test.hpp"
#include "cppa/cppa.hpp"
#include "cppa/optional_variant.hpp"
using namespace std;
using namespace cppa;
namespace { std::atomic<size_t> some_struct_instances; }
struct some_struct {
some_struct() { ++some_struct_instances; }
some_struct(const some_struct&) { ++some_struct_instances; }
~some_struct() { --some_struct_instances; }
};
struct int_visitor {
int operator()(none_t) const { return -1; }
int operator()(int i) const { return i; }
int operator()(const some_struct&) const { return 0; }
};
using dlimits = std::numeric_limits<double>;
struct double_visitor {
double operator()(none_t) const { return dlimits::signaling_NaN(); }
double operator()() const { return dlimits::quiet_NaN(); }
template<typename T>
double operator()(T value) const { return value; }
};
int main() {
CPPA_TEST(test_optional_variant);
/* run tets using primitive types */ {
using tri_type = optional_variant<void, int, double, float>;
tri_type t0;
tri_type t1{unit};
tri_type t2{0};
tri_type t3{0.0};
tri_type t4{0.0f};
CPPA_CHECK(!t0);
CPPA_CHECK(t1 && t1.is<void>());
CPPA_CHECK(t2.is<int>());
CPPA_CHECK(!t2.is<double>());
CPPA_CHECK(!t2.is<float>());
CPPA_CHECK_EQUAL(get<int>(t2), 0);
get_ref<int>(t2) = 42;
CPPA_CHECK_EQUAL(get<int>(t2), 42);
CPPA_CHECK(!t3.is<int>());
CPPA_CHECK(t3.is<double>());
CPPA_CHECK(!t3.is<float>());
CPPA_CHECK_EQUAL(get<double>(t3), 0.0);
get_ref<double>(t3) = 4.2;
CPPA_CHECK_EQUAL(get<double>(t3), 4.2);
CPPA_CHECK(!t4.is<int>());
CPPA_CHECK(!t4.is<double>());
CPPA_CHECK(t4.is<float>());
CPPA_CHECK_EQUAL(get<float>(t4), 0.0f);
get_ref<float>(t4) = 2.3f;
CPPA_CHECK_EQUAL(get<float>(t4), 2.3f);
double_visitor dv;
auto v = apply_visitor(dv, t0);
CPPA_CHECK(v != v); // only true if v is NaN
v = apply_visitor(dv, t1);
CPPA_CHECK(v != v); // only true if v is NaN
CPPA_CHECK_EQUAL(apply_visitor(dv, t2), 42.0);
CPPA_CHECK_EQUAL(apply_visitor(dv, t3), 4.2);
// converting 2.3f to double is not exactly 2.3
CPPA_CHECK_EQUAL(apply_visitor(dv, t4), static_cast<double>(2.3f));
t4 = 1;
CPPA_CHECK(t4 && t4.is<int>() && get<int>(t4) == 1);
t4 = none_t{};
CPPA_CHECK(!t4);
}
/* run tests using user-defined types */ {
using tri_type = optional_variant<int, some_struct>;
tri_type t0;
tri_type t1{42};
CPPA_CHECK_EQUAL(some_struct_instances.load(), 0);
tri_type t2{some_struct{}};
CPPA_CHECK_EQUAL(some_struct_instances.load(), 1);
CPPA_CHECK(!t0);
CPPA_CHECK(t1 && t1.is<int>() && get<int>(t1) == 42);
CPPA_CHECK(t2 && t2.is<some_struct>());
int_visitor iVisit;
CPPA_CHECK_EQUAL(apply_visitor(iVisit, t0), -1);
CPPA_CHECK_EQUAL(apply_visitor(iVisit, t1), 42);
CPPA_CHECK_EQUAL(apply_visitor(iVisit, t2), 0);
}
CPPA_CHECK_EQUAL(some_struct_instances.load(), 0);
return CPPA_TEST_RESULT();
}
......@@ -169,9 +169,9 @@ struct server : event_based_actor {
};
void compile_time_optional_variant_check(event_based_actor* self) {
typedef optional_variant<std::tuple<int, float>,
std::tuple<float, int, int>>
void compile_time_variant_check(event_based_actor* self) {
typedef variant<std::tuple<int, float>,
std::tuple<float, int, int>>
msg_type;
self->sync_send(self, atom("msg")).then([](msg_type) {});
}
......@@ -343,6 +343,6 @@ int main() {
CPPA_CHECKPOINT();
shutdown();
// shutdown warning about unused function (only performs compile-time check)
static_cast<void>(compile_time_optional_variant_check);
static_cast<void>(compile_time_variant_check);
return CPPA_TEST_RESULT();
}
......@@ -39,15 +39,21 @@ using namespace cppa::placeholders;
#define CPPA_CHECK_INVOKED(FunName, Args) \
invoked.clear(); \
if ( !( FunName Args ) || invoked != #FunName ) { \
CPPA_FAILURE("invocation of " #FunName " failed"); \
} else { CPPA_CHECKPOINT(); } static_cast<void>(42)
{ \
auto res = FunName Args ; \
if (get<none_t>(&res) || invoked != #FunName ) { \
CPPA_FAILURE("invocation of " #FunName " failed"); \
} else { CPPA_CHECKPOINT(); } \
} static_cast<void>(42)
#define CPPA_CHECK_NOT_INVOKED(FunName, Args) \
invoked.clear(); \
if ( FunName Args || invoked == #FunName ) { \
CPPA_FAILURE(#FunName " erroneously invoked"); \
} else { CPPA_CHECKPOINT(); } static_cast<void>(42)
{ \
auto res = FunName Args ; \
if (!get<none_t>(&res) || invoked == #FunName ) { \
CPPA_FAILURE(#FunName " erroneously invoked"); \
} else { CPPA_CHECKPOINT(); } \
} static_cast<void>(42)
namespace {
......
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