Commit 4a249b84 authored by Dominik Charousset's avatar Dominik Charousset

Nicer static assert message for typed behaviors

parent 00c9ca71
...@@ -87,24 +87,47 @@ struct ctm_cmp<typed_mpi<In, L, R>, ...@@ -87,24 +87,47 @@ struct ctm_cmp<typed_mpi<In, L, R>,
typed_mpi<In, R, empty_type_list>> typed_mpi<In, R, empty_type_list>>
: std::true_type { }; : std::true_type { };
template <class A, class B> template <class A, class B, int Pos = 0>
struct ctm : std::false_type { }; struct ctm_impl { // : std::integral_constant<int, -2> {
// -2 means: to few message handlers defined
template <> static constexpr int value = (tl_size<A>::value < tl_size<B>::value)
struct ctm<empty_type_list, empty_type_list> : std::true_type { }; ? -2
: -3;
template <class A, class... As, class... Bs> };
struct ctm<type_list<A, As...>, type_list<Bs...>>
: std::conditional< template <int Pos>
sizeof...(As) + 1 != sizeof...(Bs), struct ctm_impl<empty_type_list, empty_type_list, Pos>
std::false_type, : std::integral_constant<int, -1> {
ctm<type_list<As...>, // everything's fine, -1 means: no mismatch found (both sets are empty)
typename tl_filter_not< };
type_list<Bs...>,
tbind<ctm_cmp, A>::template type template <class X, class... Xs, class... Ys, int Pos>
>::type struct ctm_impl<type_list<X, Xs...>, type_list<Ys...>, Pos> {
> using next_ys =
>::type { }; typename tl_filter_not<
type_list<Ys...>,
tbind<ctm_cmp, X>::template type
>::type;
static constexpr int value =
// check if filter_not did remove something
sizeof...(Ys) == tl_size<next_ys>::value
? Pos // error at this position
: ctm_impl<type_list<Xs...>, next_ys, Pos + 1>::value;
};
template <class X, class Y>
struct ctm {
// -3 means too many handler, -2 means too few, -1 means OK, everything else
// mismatch at that position
static constexpr size_t num_xs = tl_size<X>::value;
static constexpr size_t num_ys = tl_size<Y>::value;
/*
static constexpr int value = num_xs != num_ys
? num_xs > num_ys ? -3 : -2
: ctm_impl<X, Y, 0>::value;
*/
static constexpr int value = ctm_impl<X, Y, 0>::value;
};
} // namespace detail } // namespace detail
} // namespace caf } // namespace caf
......
...@@ -136,10 +136,47 @@ struct type_checker<type_pair<Opt1, Opt2>, F1, F2> { ...@@ -136,10 +136,47 @@ struct type_checker<type_pair<Opt1, Opt2>, F1, F2> {
} }
}; };
template <int X, int Pos>
struct static_error_printer {
static_assert(X != Pos, "unexpected handler some position > 20");
};
template <int X>
struct static_error_printer<X, -3> {
static_assert(X == -1, "too few message handlers defined");
};
template <int X>
struct static_error_printer<X, -2> {
static_assert(X == -1, "too many message handlers defined");
};
template <int X>
struct static_error_printer<X, -1> {
// everything' fine
};
#define CAF_STATICERR(Pos) \
template <int X> \
struct static_error_printer< X, Pos > { \
static_assert(X == -1, "unexpected handler at position " #Pos ); \
}
CAF_STATICERR( 0); CAF_STATICERR( 1); CAF_STATICERR( 2);
CAF_STATICERR( 3); CAF_STATICERR( 4); CAF_STATICERR( 5);
CAF_STATICERR( 6); CAF_STATICERR( 7); CAF_STATICERR( 8);
CAF_STATICERR( 9); CAF_STATICERR(10); CAF_STATICERR(11);
CAF_STATICERR(12); CAF_STATICERR(13); CAF_STATICERR(14);
CAF_STATICERR(15); CAF_STATICERR(16); CAF_STATICERR(17);
CAF_STATICERR(18); CAF_STATICERR(19); CAF_STATICERR(20);
template <class A, class B, template <class, class> class Predicate> template <class A, class B, template <class, class> class Predicate>
struct static_asserter { struct static_asserter {
static void verify_match() { static void verify_match() {
static_assert(Predicate<A, B>::value, "exact match needed"); static constexpr int x = Predicate<A, B>::value;
static_error_printer<x, x> dummy;
static_cast<void>(dummy);
} }
}; };
......
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