diff --git a/libuavcan/include/uavcan/internal/method_binder.hpp b/libuavcan/include/uavcan/internal/method_binder.hpp index 768533d61a..8d42ff1153 100644 --- a/libuavcan/include/uavcan/internal/method_binder.hpp +++ b/libuavcan/include/uavcan/internal/method_binder.hpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace uavcan { @@ -24,7 +25,8 @@ public: : obj_(o) , fun_(f) { - if (!o || !f) + if (!try_implicit_cast(o, true) || + !try_implicit_cast(f, true)) { #if UAVCAN_EXCEPTIONS throw std::runtime_error(typeid(*this).name()); diff --git a/libuavcan/include/uavcan/internal/util.hpp b/libuavcan/include/uavcan/internal/util.hpp index 15ab6e7bfa..8154223852 100644 --- a/libuavcan/include/uavcan/internal/util.hpp +++ b/libuavcan/include/uavcan/internal/util.hpp @@ -74,6 +74,39 @@ template struct BooleanType { }; typedef BooleanType TrueType; typedef BooleanType FalseType; +/** + * Relations + */ +template +class IsImplicitlyConvertibleFromTo +{ + template static U returner(); + + struct True_ { char x[2]; }; + struct False_ { }; + + static True_ test(const T2 &); + static False_ test(...); + +public: + enum { Result = sizeof(True_) == sizeof(IsImplicitlyConvertibleFromTo::test(returner())) }; +}; + + +template +struct TryImplicitCastImpl +{ + static To impl(const From& from, const To&, TrueType) { return To(from); } + static To impl(const From&, const To& default_, FalseType) { return default_; } +}; + +template +To try_implicit_cast(const From& from, const To& default_ = To()) +{ + return TryImplicitCastImpl::impl(from, default_, + BooleanType::Result>()); +} + } /// Ensure that conditional comilation macros are present diff --git a/libuavcan/include/uavcan/timer.hpp b/libuavcan/include/uavcan/timer.hpp index 14f149f5a0..a6ec5bf6f9 100644 --- a/libuavcan/include/uavcan/timer.hpp +++ b/libuavcan/include/uavcan/timer.hpp @@ -66,13 +66,18 @@ public: TimerEventForwarder(Scheduler& node, Functor functor) : Timer(node) , functor_(functor) - { } + { + assert(try_implicit_cast(functor, true)); + } const Functor& getFunctor() const { return functor_; } void onTimerEvent(const TimerEvent& event) { - functor_(event); + if (try_implicit_cast(functor_, true)) + functor_(event); + else + assert(0); } };