diff --git a/any.hpp b/any.hpp index c852c1b..a381ab3 100644 --- a/any.hpp +++ b/any.hpp @@ -19,6 +19,7 @@ #include #include #include +#include namespace linb { @@ -110,6 +111,32 @@ class any final any(std::forward(value)).swap(*this); return *this; } + + template::value>::type* = 0> + bool operator==(const T &value) const + { + if(is_typed(typeid(T))) + { + auto resultPtr = cast(); + if (resultPtr != nullptr) + return value == *resultPtr; + } + return false; + } + + bool operator==(const any &rhs) const + { + if(is_typed(rhs.type())) + { + if (vtable->requires_allocation) + return storage.dynamic == rhs.storage.dynamic; + + return vtable->data_size == rhs.vtable->data_size && + ::memcmp(storage.stack.__data, rhs.storage.stack.__data, vtable->data_size) == 0; + } + return false; + } + /// If not empty, destroys the contained object. void clear() noexcept @@ -178,6 +205,10 @@ class any final { // Note: The caller is responssible for doing .vtable = nullptr after destructful operations // such as destroy() and/or move(). + + const bool requires_allocation; + + const size_t data_size; /// The type of the object this vtable is for. const std::type_info& (*type)() noexcept; @@ -279,6 +310,7 @@ class any final { using VTableType = typename std::conditional::value, vtable_dynamic, vtable_stack>::type; static vtable_type table = { + requires_allocation::value, sizeof(T), VTableType::type, VTableType::destroy, VTableType::copy, VTableType::move, VTableType::swap, @@ -381,22 +413,62 @@ namespace detail /// Performs *any_cast>>(&operand), or throws bad_any_cast on failure. template -inline ValueType any_cast(const any& operand) +inline ValueType any_cast(const any& operand, typename std::enable_if::value>::type* = 0) { auto p = any_cast::type>::type>(&operand); if(p == nullptr) throw bad_any_cast(); return *p; } +template +inline typename std::enable_if::value, ValueType>::type any_cast(const any& operand) +{ + auto p = any_cast::type>::type>(&operand); + if(p == nullptr) return nullptr; + return *p; +} + /// Performs *any_cast>(&operand), or throws bad_any_cast on failure. template -inline ValueType any_cast(any& operand) +inline ValueType any_cast(any& operand, typename std::enable_if::value>::type* = 0) { auto p = any_cast::type>(&operand); if(p == nullptr) throw bad_any_cast(); return *p; } +template +inline typename std::enable_if::value, ValueType>::type any_cast(any& operand) +{ + auto p = any_cast::type>(&operand); + if(p == nullptr) return nullptr; + return *p; +} + +template +inline bool any_cast_test(const any& operand, ValueType const& result) +{ + auto p = any_cast::type>::type>(&operand); + if(p != nullptr) + { + result = *p; + return true; + } + return false; +} + +template +inline bool any_cast_test(any& operand, ValueType& result) +{ + auto p = any_cast::type>(&operand); + if(p != nullptr) + { + result = *p; + return true; + } + return false; +} + /// /// If ANY_IMPL_ANYCAST_MOVEABLE is not defined, does as N4562 specifies: /// Performs *any_cast>(&operand), or throws bad_any_cast on failure.