Commit abf66536 authored by Dominik Charousset's avatar Dominik Charousset

Make variant more C++17 compliant, close #525

parent 42309315
...@@ -204,7 +204,7 @@ public: ...@@ -204,7 +204,7 @@ public:
T T
>::type >::type
>::type; >::type;
if (get<cfg_type>(&x) && assign_config_value(ref_, get<cfg_type>(x))) if (get_if<cfg_type>(&x) && assign_config_value(ref_, get<cfg_type>(x)))
return; return;
type_name_visitor tnv; type_name_visitor tnv;
report_type_error(ln, x, tnv(ref_), errors); report_type_error(ln, x, tnv(ref_), errors);
...@@ -262,7 +262,7 @@ public: ...@@ -262,7 +262,7 @@ public:
>::type >::type
>::type; >::type;
value_type tmp; value_type tmp;
if (get<cfg_type>(&x) && assign_config_value(tmp, get<cfg_type>(x))) { if (get_if<cfg_type>(&x) && assign_config_value(tmp, get<cfg_type>(x))) {
ref_.insert(ref_.end(), std::move(tmp)); ref_.insert(ref_.end(), std::move(tmp));
return; return;
} }
......
...@@ -168,7 +168,7 @@ protected: ...@@ -168,7 +168,7 @@ protected:
} }
} else { } else {
if (derived.current_stream_state_ != derived.streams_.end()) { if (derived.current_stream_state_ != derived.streams_.end()) {
apply_visitor(derived, x.content); visit(derived, x.content);
} else { } else {
CAF_LOG_ERROR("Unable to access required stream and/or path state."); CAF_LOG_ERROR("Unable to access required stream and/or path state.");
derived.fail(sec::invalid_stream_state); derived.fail(sec::invalid_stream_state);
......
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
namespace caf { namespace caf {
constexpr size_t variant_npos = static_cast<size_t>(-1);
template <class T> template <class T>
struct variant_assign_helper { struct variant_assign_helper {
using result_type = void; using result_type = void;
...@@ -102,11 +104,15 @@ public: ...@@ -102,11 +104,15 @@ public:
static constexpr int max_type_id = sizeof...(Ts) - 1; static constexpr int max_type_id = sizeof...(Ts) - 1;
static_assert(sizeof...(Ts) <= 20, "Too many template arguments"); static_assert(sizeof...(Ts) <= 20, "Too many template arguments given.");
static_assert(sizeof...(Ts) > 0, "No template argument given.");
static_assert(!detail::tl_exists<types, std::is_reference>::value, static_assert(!detail::tl_exists<types, std::is_reference>::value,
"Cannot create a variant of references"); "Cannot create a variant of references");
using type0 = typename detail::tl_at<types, 0>::type;
variant& operator=(const variant& other) { variant& operator=(const variant& other) {
variant_assign_helper<variant> helper{*this}; variant_assign_helper<variant> helper{*this};
other.apply(helper); other.apply(helper);
...@@ -119,13 +125,15 @@ public: ...@@ -119,13 +125,15 @@ public:
return *this; return *this;
} }
variant() : type_(0) { variant() : type_(variant_npos) {
// never empty // Never empty ...
set(typename detail::tl_head<types>::type()); set(typename detail::tl_head<types>::type());
// ... unless an exception was thrown above.
type_ = 0;
} }
template <class U> template <class U>
variant(U&& arg) : type_(-1) { variant(U&& arg) : type_(variant_npos) {
set(std::forward<U>(arg)); set(std::forward<U>(arg));
} }
...@@ -135,12 +143,12 @@ public: ...@@ -135,12 +143,12 @@ public:
return *this; return *this;
} }
variant(const variant& other) : type_(-1) { variant(const variant& other) : type_(variant_npos) {
variant_assign_helper<variant> helper{*this}; variant_assign_helper<variant> helper{*this};
other.apply(helper); other.apply(helper);
} }
variant(variant&& other) : type_(-1) { variant(variant&& other) : type_(variant_npos) {
variant_move_helper<variant> helper{*this}; variant_move_helper<variant> helper{*this};
other.apply(helper); other.apply(helper);
} }
...@@ -149,6 +157,14 @@ public: ...@@ -149,6 +157,14 @@ public:
destroy_data(); destroy_data();
} }
constexpr size_t index() const {
return static_cast<size_t>(type_);
}
bool valueless_by_exception() const {
return index() == variant_npos;
}
/// @cond PRIVATE /// @cond PRIVATE
template <int Pos> template <int Pos>
bool is(std::integral_constant<int, Pos>) const { bool is(std::integral_constant<int, Pos>) const {
...@@ -177,22 +193,20 @@ public: ...@@ -177,22 +193,20 @@ public:
} }
template <class Visitor> template <class Visitor>
typename Visitor::result_type apply(Visitor& visitor) const { auto apply(Visitor&& visitor) const
return apply_impl(*this, visitor); -> decltype(visitor(std::declval<const type0&>())) {
return apply_impl(*this, std::forward<Visitor>(visitor));
} }
template <class Visitor> template <class Visitor>
typename Visitor::result_type apply(Visitor& visitor) { auto apply(Visitor&& visitor) -> decltype(visitor(std::declval<type0&>())) {
return apply_impl(*this, visitor); return apply_impl(*this, std::forward<Visitor>(visitor));
}
int8_t type_tag() {
return static_cast<int8_t>(type_);
} }
template <class Self, class Visitor> template <class Self, class Visitor>
static typename Visitor::result_type static auto apply_impl(Self& x, Visitor&& f) -> decltype(
apply_impl(Self& x, Visitor& f) { f(std::declval<typename std::conditional<std::is_const<Self>::value,
const type0, type0>::type&>())) {
switch (x.type_) { switch (x.type_) {
default: CAF_RAISE_ERROR("invalid type found"); default: CAF_RAISE_ERROR("invalid type found");
CAF_VARIANT_CASE(0); CAF_VARIANT_CASE(0);
...@@ -221,7 +235,7 @@ public: ...@@ -221,7 +235,7 @@ public:
private: private:
inline void destroy_data() { inline void destroy_data() {
if (type_ == -1) return; // nothing to do if (type_ == variant_npos) return; // nothing to do
detail::variant_data_destructor f; detail::variant_data_destructor f;
apply(f); apply(f);
} }
...@@ -273,10 +287,16 @@ private: ...@@ -273,10 +287,16 @@ private:
other.apply(helper); other.apply(helper);
} }
int type_; size_t type_;
detail::variant_data<typename lift_void<Ts>::type...> data_; detail::variant_data<typename lift_void<Ts>::type...> data_;
}; };
template <class T>
struct is_variant : std::false_type {};
template <class... Ts>
struct is_variant<variant<Ts...>> : std::true_type {};
/// @relates variant /// @relates variant
template <class T, class... Us> template <class T, class... Us>
T& get(variant<Us...>& value) { T& get(variant<Us...>& value) {
...@@ -297,7 +317,7 @@ const T& get(const variant<Us...>& value) { ...@@ -297,7 +317,7 @@ const T& get(const variant<Us...>& value) {
/// @relates variant /// @relates variant
template <class T, class... Us> template <class T, class... Us>
T* get(variant<Us...>* value) { T* get_if(variant<Us...>* value) {
using namespace detail; using namespace detail;
int_token<tl_index_where<type_list<Us...>, int_token<tl_index_where<type_list<Us...>,
tbind<is_same_ish, T>::template type>::value> token; tbind<is_same_ish, T>::template type>::value> token;
...@@ -308,22 +328,33 @@ T* get(variant<Us...>* value) { ...@@ -308,22 +328,33 @@ T* get(variant<Us...>* value) {
/// @relates variant /// @relates variant
template <class T, class... Us> template <class T, class... Us>
const T* get(const variant<Us...>* value) { const T* get_if(const variant<Us...>* value) {
// compiler implicitly restores const because of the return type // compiler implicitly restores const because of the return type
return get<T>(const_cast<variant<Us...>*>(value)); return get_if<T>(const_cast<variant<Us...>*>(value));
} }
/// @relates variant /// @relates variant
template <class Visitor, class... Ts> template <class Visitor, class... Ts>
typename Visitor::result_type typename Visitor::result_type
apply_visitor(Visitor& visitor, const variant<Ts...>& data) { CAF_DEPRECATED apply_visitor(Visitor& visitor, const variant<Ts...>& data) {
return data.apply(visitor);
}
/// @relates variant
template <class Visitor, class Variant,
class E =
typename std::enable_if<
is_variant<typename std::decay<Variant>::type>::value
>::type>
auto visit(Visitor&& visitor, Variant&& data)
-> decltype(data.apply(std::forward<Visitor>(visitor))) {
return data.apply(visitor); return data.apply(visitor);
} }
/// @relates variant /// @relates variant
template <class Visitor, class... Ts> template <class Visitor, class... Ts>
typename Visitor::result_type typename Visitor::result_type
apply_visitor(Visitor& visitor, variant<Ts...>& data) { CAF_DEPRECATED apply_visitor(Visitor& visitor, variant<Ts...>& data) {
return data.apply(visitor); return data.apply(visitor);
} }
...@@ -342,7 +373,7 @@ struct variant_compare_helper { ...@@ -342,7 +373,7 @@ struct variant_compare_helper {
} }
template <class U> template <class U>
bool operator()(const U& rhs) const { bool operator()(const U& rhs) const {
auto ptr = get<U>(&lhs); auto ptr = get_if<U>(&lhs);
return ptr ? *ptr == rhs : false; return ptr ? *ptr == rhs : false;
} }
}; };
...@@ -351,7 +382,7 @@ struct variant_compare_helper { ...@@ -351,7 +382,7 @@ struct variant_compare_helper {
template <class... Ts> template <class... Ts>
bool operator==(const variant<Ts...>& x, const variant<Ts...>& y) { bool operator==(const variant<Ts...>& x, const variant<Ts...>& y) {
variant_compare_helper<variant<Ts...>> f{x}; variant_compare_helper<variant<Ts...>> f{x};
return apply_visitor(f, y); return visit(f, y);
} }
/// @relates variant /// @relates variant
...@@ -370,7 +401,7 @@ bool operator==(const variant<Ts...>& x, const T& y) { ...@@ -370,7 +401,7 @@ bool operator==(const variant<Ts...>& x, const T& y) {
/// @relates variant /// @relates variant
template <class T> template <class T>
struct variant_reader { struct variant_reader {
int8_t& type_tag; size_t& type_tag;
T& x; T& x;
}; };
...@@ -378,7 +409,8 @@ struct variant_reader { ...@@ -378,7 +409,8 @@ struct variant_reader {
template <class Inspector, class... Ts> template <class Inspector, class... Ts>
typename Inspector::result_type typename Inspector::result_type
inspect(Inspector& f, variant_reader<variant<Ts...>>& x) { inspect(Inspector& f, variant_reader<variant<Ts...>>& x) {
return variant<Ts...>::apply_impl(x.x, f); return x.x.apply(f);
//return variant<Ts...>::apply_impl(x.x, f);
} }
/// @relates variant /// @relates variant
...@@ -386,7 +418,7 @@ template <class Inspector, class... Ts> ...@@ -386,7 +418,7 @@ template <class Inspector, class... Ts>
typename std::enable_if<Inspector::reads_state, typename std::enable_if<Inspector::reads_state,
typename Inspector::result_type>::type typename Inspector::result_type>::type
inspect(Inspector& f, variant<Ts...>& x) { inspect(Inspector& f, variant<Ts...>& x) {
auto type_tag = x.type_tag(); auto type_tag = x.index();
variant_reader<variant<Ts...>> helper{type_tag, x}; variant_reader<variant<Ts...>> helper{type_tag, x};
return f(meta::omittable(), type_tag, helper); return f(meta::omittable(), type_tag, helper);
} }
...@@ -394,7 +426,7 @@ inspect(Inspector& f, variant<Ts...>& x) { ...@@ -394,7 +426,7 @@ inspect(Inspector& f, variant<Ts...>& x) {
/// @relates variant /// @relates variant
template <class T> template <class T>
struct variant_writer { struct variant_writer {
int8_t& type_tag; size_t& type_tag;
T& x; T& x;
}; };
...@@ -432,7 +464,7 @@ template <class Inspector, class... Ts> ...@@ -432,7 +464,7 @@ template <class Inspector, class... Ts>
typename std::enable_if<Inspector::writes_state, typename std::enable_if<Inspector::writes_state,
typename Inspector::result_type>::type typename Inspector::result_type>::type
inspect(Inspector& f, variant<Ts...>& x) { inspect(Inspector& f, variant<Ts...>& x) {
int8_t type_tag; size_t type_tag;
variant_writer<variant<Ts...>> helper{type_tag, x}; variant_writer<variant<Ts...>> helper{type_tag, x};
return f(meta::omittable(), type_tag, helper); return f(meta::omittable(), type_tag, helper);
} }
......
...@@ -79,7 +79,7 @@ void config_option::report_type_error(size_t ln, config_value& x, ...@@ -79,7 +79,7 @@ void config_option::report_type_error(size_t ln, config_value& x,
type_name_visitor tnv; type_name_visitor tnv;
*out << "error in line " << ln << ": expected " *out << "error in line " << ln << ": expected "
<< expected << " found " << expected << " found "
<< apply_visitor(tnv, x) << '\n'; << visit(tnv, x) << '\n';
} }
} // namespace caf } // namespace caf
...@@ -654,7 +654,7 @@ bool scheduled_actor::handle_stream_msg(mailbox_element& x, ...@@ -654,7 +654,7 @@ bool scheduled_actor::handle_stream_msg(mailbox_element& x,
auto& sm = x.content().get_mutable_as<stream_msg>(0); auto& sm = x.content().get_mutable_as<stream_msg>(0);
auto e = streams_.end(); auto e = streams_.end();
stream_msg_visitor f{this, sm.sid, streams_.find(sm.sid), e, active_behavior}; stream_msg_visitor f{this, sm.sid, streams_.find(sm.sid), e, active_behavior};
auto res = apply_visitor(f, sm.content); auto res = visit(f, sm.content);
auto success = (res.first == none); auto success = (res.first == none);
auto i = res.second; auto i = res.second;
if (!success) { if (!success) {
......
...@@ -129,7 +129,7 @@ struct fixture { ...@@ -129,7 +129,7 @@ struct fixture {
optional<std::ostream&>) { optional<std::ostream&>) {
message_visitor mv; message_visitor mv;
anon_send(config_server, put_atom::value, anon_send(config_server, put_atom::value,
std::move(key), apply_visitor(mv, value)); std::move(key), visit(mv, value));
}; };
load_impl(consume, str); load_impl(consume, str);
} }
...@@ -189,7 +189,7 @@ struct fixture { ...@@ -189,7 +189,7 @@ struct fixture {
T T
>::type >::type
>::type; >::type;
auto ptr = get<type>(&cv); auto ptr = get_if<type>(&cv);
return ptr != nullptr && detail::safe_equal(*ptr, what); return ptr != nullptr && detail::safe_equal(*ptr, what);
} }
......
...@@ -68,7 +68,7 @@ ostream& operator<<(ostream& out, const maybe<T>& x) { ...@@ -68,7 +68,7 @@ ostream& operator<<(ostream& out, const maybe<T>& x) {
using std::to_string; using std::to_string;
using caf::to_string; using caf::to_string;
using caf::io::basp::to_string; using caf::io::basp::to_string;
if (get<anything>(&x) != nullptr) if (caf::get_if<anything>(&x) != nullptr)
return out << "*"; return out << "*";
return out << to_string(get<T>(x)); return out << to_string(get<T>(x));
} }
...@@ -79,7 +79,7 @@ namespace caf { ...@@ -79,7 +79,7 @@ namespace caf {
template <class T, class U> template <class T, class U>
bool operator==(const maybe<T>& x, const U& y) { bool operator==(const maybe<T>& x, const U& y) {
return get<anything>(&x) != nullptr || get<T>(x) == y; return get_if<anything>(&x) != nullptr || get<T>(x) == y;
} }
template <class T, class U> template <class T, class U>
...@@ -89,7 +89,7 @@ bool operator==(const T& x, const maybe<U>& y) { ...@@ -89,7 +89,7 @@ bool operator==(const T& x, const maybe<U>& y) {
template <class T> template <class T>
std::string to_string(const maybe<T>& x) { std::string to_string(const maybe<T>& x) {
return !get<anything>(&x) ? std::string{"*"} : deep_to_string(get<T>(x)); return !get_if<anything>(&x) ? std::string{"*"} : deep_to_string(get<T>(x));
} }
} // namespace caf } // namespace caf
......
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