Commit b6a18114 authored by Dominik Charousset's avatar Dominik Charousset

Make typed handles unassignable on mismatch

Use SFINAE to make assignment of invalid `typed_actor` handles impossible
instead instead of checking correctness of an assignment with `typed_actor`.
parent 6a6f8dfb
...@@ -48,15 +48,15 @@ class typed_broker; ...@@ -48,15 +48,15 @@ class typed_broker;
} // namespace experimental } // namespace experimental
} // namespace io } // namespace io
/// Identifies a strongly typed actor. /// Identifies a statically typed actor.
/// @tparam Sigs Signature of this actor as `replies_to<...>::with<...>` /// @tparam Sigs Signature of this actor as `replies_to<...>::with<...>`
/// parameter pack. /// parameter pack.
template <class... Sigs> template <class... Sigs>
class typed_actor class typed_actor : detail::comparable<typed_actor<Sigs...>>,
: detail::comparable<typed_actor<Sigs...>>, detail::comparable<typed_actor<Sigs...>, actor_addr>,
detail::comparable<typed_actor<Sigs...>, actor_addr>, detail::comparable<typed_actor<Sigs...>,
detail::comparable<typed_actor<Sigs...>, invalid_actor_addr_t> { invalid_actor_addr_t> {
public:
friend class local_actor; friend class local_actor;
// friend with all possible instantiations // friend with all possible instantiations
...@@ -67,8 +67,6 @@ class typed_actor ...@@ -67,8 +67,6 @@ class typed_actor
template <class T, typename U> template <class T, typename U>
friend T actor_cast(const U&); friend T actor_cast(const U&);
public:
/// Creates a new `typed_actor` type by extending this one with `Es...`. /// Creates a new `typed_actor` type by extending this one with `Es...`.
template <class... Es> template <class... Es>
using extend = typed_actor<Sigs..., Es...>; using extend = typed_actor<Sigs..., Es...>;
...@@ -95,20 +93,38 @@ public: ...@@ -95,20 +93,38 @@ public:
typed_actor& operator=(typed_actor&&) = default; typed_actor& operator=(typed_actor&&) = default;
typed_actor& operator=(const typed_actor&) = default; typed_actor& operator=(const typed_actor&) = default;
template <class... OtherSigs> template <class... OtherSigs,
typed_actor(const typed_actor<OtherSigs...>& other) { class Enable = typename std::enable_if<
set(std::move(other)); detail::tl_is_strict_subset<
detail::type_list<Sigs...>,
detail::type_list<OtherSigs...>
>::value
>::type>
typed_actor(const typed_actor<OtherSigs...>& other) : ptr_(other.ptr_) {
// nop
} }
template <class... OtherSigs> template <class... OtherSigs,
class Enable = typename std::enable_if<
detail::tl_is_strict_subset<
detail::type_list<Sigs...>,
detail::type_list<OtherSigs...>
>::value
>::type>
typed_actor& operator=(const typed_actor<OtherSigs...>& other) { typed_actor& operator=(const typed_actor<OtherSigs...>& other) {
set(std::move(other)); ptr_ = other.ptr_;
return *this; return *this;
} }
template <class Impl> template <class Impl,
typed_actor(intrusive_ptr<Impl> other) { class Enable = typename std::enable_if<
set(other); detail::tl_is_strict_subset<
detail::type_list<Sigs...>,
typename Impl::signatures
>::value
>::type>
typed_actor(intrusive_ptr<Impl> other) : ptr_(std::move(other)) {
// nop
} }
abstract_actor* operator->() const { abstract_actor* operator->() const {
...@@ -124,15 +140,15 @@ public: ...@@ -124,15 +140,15 @@ public:
return ptr_ ? ptr_->address() : actor_addr{}; return ptr_ ? ptr_->address() : actor_addr{};
} }
inline intptr_t compare(const actor_addr& rhs) const { intptr_t compare(const actor_addr& rhs) const {
return address().compare(rhs); return address().compare(rhs);
} }
inline intptr_t compare(const typed_actor& other) const { intptr_t compare(const typed_actor& other) const {
return compare(other.address()); return compare(other.address());
} }
inline intptr_t compare(const invalid_actor_addr_t&) const { intptr_t compare(const invalid_actor_addr_t&) const {
return ptr_ ? 1 : 0; return ptr_ ? 1 : 0;
} }
...@@ -140,36 +156,24 @@ public: ...@@ -140,36 +156,24 @@ public:
return {Sigs::static_type_name()...}; return {Sigs::static_type_name()...};
} }
explicit operator bool() const { return static_cast<bool>(ptr_); } explicit operator bool() const {
return static_cast<bool>(ptr_);
inline bool operator!() const { return ! ptr_; } }
private:
inline abstract_actor* get() const { return ptr_.get(); }
typed_actor(abstract_actor* ptr) : ptr_(ptr) {}
template <class ListA, class ListB> bool operator!() const {
inline void check_signatures() { return !ptr_;
static_assert(detail::tl_is_strict_subset<ListA, ListB>::value,
"'this' must be a strict subset of 'other'");
} }
template <class... OtherSigs> private:
inline void set(const typed_actor<OtherSigs...>& other) { abstract_actor* get() const {
check_signatures<detail::type_list<Sigs...>, detail::type_list<OtherSigs...>>(); return ptr_.get();
ptr_ = other.ptr_;
} }
template <class Impl> typed_actor(abstract_actor* ptr) : ptr_(ptr) {
inline void set(intrusive_ptr<Impl>& other) { // nop
check_signatures<detail::type_list<Sigs...>, typename Impl::signatures>();
ptr_ = std::move(other);
} }
abstract_actor_ptr ptr_; abstract_actor_ptr ptr_;
}; };
} // namespace caf } // namespace caf
......
...@@ -45,6 +45,9 @@ using dummy2 = dummy1::extend<reacts_to<ok_atom>>; ...@@ -45,6 +45,9 @@ using dummy2 = dummy1::extend<reacts_to<ok_atom>>;
static_assert(std::is_convertible<dummy2, dummy1>::value, static_assert(std::is_convertible<dummy2, dummy1>::value,
"handle not assignable to narrower definition"); "handle not assignable to narrower definition");
static_assert(! std::is_convertible<dummy1, dummy2>::value,
"handle is assignable to broader definition");
/****************************************************************************** /******************************************************************************
* simple request/response test * * simple request/response test *
******************************************************************************/ ******************************************************************************/
......
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