Commit d1aaf702 authored by Dominik Charousset's avatar Dominik Charousset

Integrate CAF_ERROR_CODE_ENUM macro

parent a7752756
......@@ -24,6 +24,7 @@
#include <stdexcept>
#include "caf/error.hpp"
#include "caf/timespan.hpp"
namespace caf {
......@@ -75,15 +76,6 @@ constexpr time_unit get_time_unit_from_period() {
return ratio_to_time_unit_helper<Period::num, Period::den>::value;
}
/// Represents an infinite amount of timeout for specifying "invalid" timeouts.
struct infinite_t {
constexpr infinite_t() {
// nop
}
};
static constexpr infinite_t infinite = infinite_t{};
/// Time duration consisting of a `time_unit` and a 64 bit unsigned integer.
class duration {
public:
......
......@@ -71,6 +71,12 @@ template <class T, class U = void>
using enable_if_has_error_factory_t =
typename std::enable_if<detail::error_factory<T>::specialized, U>::type;
/// @private
template <class T, class U = void>
using enable_if_can_construct_error_t = typename std::enable_if<
detail::error_factory<T>::specialized || has_make_error<T>::value, U>::type;
/// A serializable type for storing error codes with category and optional,
/// human-readable context information. Unlike error handling classes from
/// the C++ standard library, this type is serializable. It consists of an
......@@ -276,15 +282,21 @@ bool operator!=(E x, const error& y) {
return !(x == y);
}
/// @relates error
template <class Code, class... Ts>
enable_if_has_error_factory_t<Code, error> make_error(Code code, Ts&&... xs) {
return error{code, std::forward<Ts>(xs)...};
}
} // namespace caf
#define CAF_ERROR_CODE_ENUM(enum_name) \
#define CAF_ERROR_CODE_ENUM(enum_type, category_name) \
namespace caf { \
namespace detail { \
template <> \
struct error_factory<enum_name> { \
struct error_factory<enum_type> { \
static constexpr bool specialized = true; \
static constexpr atom_value category = atom(#enum_name); \
static constexpr atom_value category = atom(category_name); \
template <class... Ts> \
static message context(Ts&&... xs) { \
return make_message(std::forward<Ts>(xs)...); \
......
......@@ -91,9 +91,9 @@ public:
construct(other);
}
template <class Code, class E = enable_if_has_make_error_t<Code>>
template <class Code, class = enable_if_can_construct_error_t<Code>>
expected(Code code) : engaged_(false) {
new (std::addressof(error_)) caf::error(make_error(code));
new (std::addressof(error_)) caf::error(code);
}
expected(expected&& other) noexcept(nothrow_move) {
......@@ -139,7 +139,6 @@ public:
return *this;
}
expected& operator=(T&& x) noexcept(nothrow_move) {
if (engaged_) {
value_ = std::move(x);
......@@ -169,8 +168,8 @@ public:
}
template <class Code>
enable_if_has_make_error_t<Code, expected&> operator=(Code code) {
return *this = make_error(code);
enable_if_can_construct_error_t<Code, expected&> operator=(Code code) {
return *this = caf::error{code};
}
// -- modifiers --------------------------------------------------------------
......@@ -390,8 +389,8 @@ public:
// nop
}
template <class Code, class E = enable_if_has_make_error_t<Code>>
expected(Code code) : error_(make_error(code)) {
template <class Code, class = enable_if_can_construct_error_t<Code>>
expected(Code code) : error_(code) {
// nop
}
......@@ -402,6 +401,11 @@ public:
return *this;
}
template <class Code>
enable_if_can_construct_error_t<Code, expected&> operator=(Code code) {
error_ = caf::error{code};
}
explicit operator bool() const {
return !error_;
}
......@@ -458,4 +462,3 @@ auto operator<<(ostream& oss, const caf::expected<T>& x)
}
} // namespace std
......@@ -61,14 +61,6 @@ struct is_serializable_or_whitelisted {
|| allowed_unsafe_message_type<T>::value;
};
/// @private
template <class T>
struct has_type_id {
static constexpr bool value = detail::is_complete<type_id<T>>::value
|| is_atom_constant<T>::value
|| allowed_unsafe_message_type<T>::value;
};
/// Returns a new `message` containing the values `(x, xs...)`.
/// @relates message
template <class T, class... Ts>
......
......@@ -26,5 +26,14 @@ namespace caf {
/// A portable timespan type with nanosecond resolution.
using timespan = std::chrono::duration<int64_t, std::nano>;
} // namespace caf
/// Represents an infinite amount of timeout for specifying "invalid" timeouts.
struct infinite_t {
constexpr infinite_t() {
// nop
}
};
/// Constant for passing "no timeout" to functions such as `request`.
static constexpr infinite_t infinite = infinite_t{};
} // namespace caf
......@@ -23,7 +23,9 @@
#include <string>
#include <utility>
#include "caf/allowed_unsafe_message_type.hpp"
#include "caf/atom.hpp"
#include "caf/detail/is_complete.hpp"
#include "caf/detail/pp.hpp"
#include "caf/detail/squashed_int.hpp"
#include "caf/fwd.hpp"
......@@ -63,6 +65,17 @@ struct type_name_by_id;
/// The first type ID not reserved by CAF and its modules.
constexpr type_id_t first_custom_type_id = 200;
/// Evaluates to `true` if any of these statements holds true:
/// - `type_id<T>` is specialized
/// - `T` is an atom constant
/// - `allowed_unsafe_message_type<T>` is specialized
template <class T>
struct has_type_id {
static constexpr bool value = detail::is_complete<type_id<T>>::value
|| is_atom_constant<T>::value
|| allowed_unsafe_message_type<T>::value;
};
} // namespace caf
/// Starts a code block for registering custom types to CAF. Stores the first ID
......
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