From 356eb7fe0abb22c929ef9a9b814dba33d6ebbb6b Mon Sep 17 00:00:00 2001 From: Elia Date: Thu, 19 Oct 2017 23:02:15 +0100 Subject: [PATCH 1/3] Added any_cast_test, which returns false if value can't be cast, instead of throwing an exception --- any.hpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/any.hpp b/any.hpp index c852c1b..328b873 100644 --- a/any.hpp +++ b/any.hpp @@ -397,6 +397,30 @@ inline ValueType any_cast(any& operand) 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. From 1d5d855e3745ec5d5bf34e3aa335d56aa06e6ff2 Mon Sep 17 00:00:00 2001 From: Elia Date: Thu, 19 Oct 2017 23:03:11 +0100 Subject: [PATCH 2/3] Don't throw exceptions when any_cast fails to cast a stored pointer value, simply return nullptr --- any.hpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/any.hpp b/any.hpp index 328b873..3bbcf71 100644 --- a/any.hpp +++ b/any.hpp @@ -381,22 +381,38 @@ 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) { From 9db5b3bcc749b950aaf45ce1f76621ce78de45b3 Mon Sep 17 00:00:00 2001 From: Elia Date: Thu, 19 Oct 2017 23:03:52 +0100 Subject: [PATCH 3/3] Added equality operator to compare different any objects --- any.hpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/any.hpp b/any.hpp index 3bbcf71..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,