diff --git a/src/lib/access-casted-o.hpp b/src/lib/access-casted-o.hpp index 4b8080ff2..dcebac3f1 100644 --- a/src/lib/access-casted-o.hpp +++ b/src/lib/access-casted-o.hpp @@ -27,7 +27,7 @@ ** and the target type (type we need within the usage context). ** When instantiating AcessCasted, we get a template static function ** \c AcessCasted::access(SRC& elm), but the actual implementation - ** is chosen using boost::type_traits. If no sensible implementation can be + ** is chosen using std::type_traits. If no sensible implementation can be ** selected, \c EmptyVal::create() is invoked instead, which by default ** creates a NULL value or similar by using the no-argument ctor of the ** type TAR. Alternatively, you may define an specialisation of EmptyVal, @@ -45,89 +45,85 @@ #ifndef UTIL_ACCESS_CASTED_O_H #define UTIL_ACCESS_CASTED_O_H -#include -#include -#include -#include -#include -#include +#include namespace util { - using boost::remove_pointer; - using boost::remove_reference; - using boost::is_convertible; - using boost::is_polymorphic; - using boost::is_base_of; - using boost::enable_if; - - template - struct can_cast : boost::false_type {}; - - template - struct can_cast { enum { value = is_base_of::value };}; - - template - struct can_cast { enum { value = is_base_of::value };}; - - template - struct can_cast { enum { value = is_base_of::value };}; - - - template - struct has_RTTI - { - typedef typename remove_pointer< - typename remove_reference::type>::type TPlain; + namespace { + using std::remove_pointer; + using std::remove_reference; + using std::is_convertible; + using std::is_polymorphic; + using std::is_base_of; - enum { value = is_polymorphic::value }; - }; - - template - struct use_dynamic_downcast - { - enum { value = can_cast::value - && has_RTTI::value - && has_RTTI::value - }; - }; - - template - struct use_static_downcast - { - enum { value = can_cast::value - && ( !has_RTTI::value - || !has_RTTI::value - ) - }; - }; - - template - struct use_conversion - { - enum { value = is_convertible::value - && !( use_static_downcast::value - ||use_dynamic_downcast::value - ) - }; - }; - - - - ////////////////////////////////TODO: use lib::NullValue instead - template - struct EmptyVal - { - static X create() { return X(); } - }; - template - struct EmptyVal - { - static X*& create() { static X* nullP(0); return nullP; } - }; - + + template + struct can_cast : std::false_type {}; + + template + struct can_cast { enum { value = is_base_of::value };}; + + template + struct can_cast { enum { value = is_base_of::value };}; + + template + struct can_cast { enum { value = is_base_of::value };}; + + + template + struct hasRTTI + { + typedef typename remove_pointer< + typename remove_reference::type>::type TPlain; + + enum { value = is_polymorphic::value }; + }; + + template + struct use_dynamic_downcast + { + enum { value = can_cast::value + && hasRTTI::value + && hasRTTI::value + }; + }; + + template + struct use_static_downcast + { + enum { value = can_cast::value + && ( !hasRTTI::value + || !hasRTTI::value + ) + }; + }; + + template + struct use_conversion + { + enum { value = is_convertible::value + && !( use_static_downcast::value + ||use_dynamic_downcast::value + ) + }; + }; + + + + template + struct EmptyVal + { + static X create() { return X(); } + }; + template + struct EmptyVal + { + static X*& create() { static X* nullP(0); return nullP; } + }; + + } @@ -142,12 +138,12 @@ namespace util { }; template - struct AccessCasted : NullAccessor + struct AccessCasted_O : NullAccessor { using NullAccessor::access; template - static typename enable_if< use_dynamic_downcast, + static typename std::enable_if< use_dynamic_downcast::value, TAR >::type access (ELM& elem) { @@ -155,7 +151,7 @@ namespace util { } template - static typename enable_if< use_static_downcast, + static typename std::enable_if< use_static_downcast::value, TAR >::type access (ELM& elem) { @@ -163,7 +159,7 @@ namespace util { } template - static typename enable_if< use_conversion, + static typename std::enable_if< use_conversion::value, TAR >::type access (ELM& elem) { diff --git a/src/lib/opaque-holder.hpp b/src/lib/opaque-holder.hpp index 5afe4fbd0..ec8e418ab 100644 --- a/src/lib/opaque-holder.hpp +++ b/src/lib/opaque-holder.hpp @@ -69,7 +69,7 @@ #include "lib/error.hpp" #include "lib/bool-checkable.hpp" -#include "lib/access-casted-o.hpp" +#include "lib/access-casted.hpp" #include "lib/util.hpp" #include @@ -78,7 +78,8 @@ namespace lib { - using lumiera::error::LUMIERA_ERROR_WRONG_TYPE; + namespace error = lumiera::error; + using util::isSameObject; using util::unConst; @@ -131,26 +132,9 @@ namespace lib { if (asBase) return asBase; - throw lumiera::error::Logic ("Unable to convert concrete object to Base interface" - , LUMIERA_ERROR_WRONG_TYPE - ); - } - - template - static SUB* - access (Base* asBase) - { - // Because we don't know anything about the involved types, - // we need to exclude a brute force static cast - // (which might slice or reinterpret or even cause SEGV) - if (!util::use_static_downcast::value) - { - SUB* content = util::AccessCasted::access (asBase); - return content; - // might be NULL - } - else - return 0; + throw error::Logic ("Unable to convert concrete object to Base interface" + , error::LUMIERA_ERROR_WRONG_TYPE + ); } }; @@ -175,13 +159,6 @@ namespace lib { { return static_cast (&obj); } - - template - static SUB* - access (Base*) - { - return 0; - } }; @@ -241,7 +218,8 @@ namespace lib { BaseP getBase() const { - throw lumiera::error::Invalid("accessing empty holder"); + throw error::Invalid("accessing empty holder" + , error::LUMIERA_ERROR_BOTTOM_VALUE); } virtual void @@ -455,19 +433,12 @@ namespace lib { /** re-accessing the concrete contained object. - * When the specified type is exactly the same - * as used when storing the object, we can directly - * re-access the buffer. Otherwise, a conversion might - * be possible going through the Base type, depending - * on the actual types involved and the AccessPolicy. - * But, as we don't "know" the actual type of the object - * in storage, a \em static upcast to any type \em between - * the concrete object type and the base type has to be - * ruled out for safety reasons. When the contained object - * has RTTI, a \em dynamic cast can be performed in this - * situation. You might consider using visitor.hpp instead - * if this imposes a serious limitation. - * @throws lumiera::error::Logic when conversion/access fails + * This requires exact knowledge of the actual type + * of the element currently in storage. OpaqueHolder + * does not provide any "probing" or visitation mechanism. + * @remarks You might consider lib::Variant or some visitor instead. + * @throws lumiera::error::Logic when conversion/access fails + * @throws lumiera::error::Invalid when accessing an empty holder */ template SUB& get() const @@ -479,16 +450,14 @@ namespace lib { if (actual) return actual->get(); - // second try: maybe we can perform a dynamic downcast - // or direct conversion to the actual target type. - SUB* content = AccessPolicy::template access (asBase()); - if (content) - return *content; - - throw lumiera::error::Logic ("Attempt to access OpaqueHolder's contents " - "specifying incompatible target type" - , LUMIERA_ERROR_WRONG_TYPE - ); + if (this->empty()) + throw error::Invalid("accessing empty holder" + , error::LUMIERA_ERROR_BOTTOM_VALUE); + else + throw error::Logic ("Attempt to access OpaqueHolder's contents " + "specifying incompatible target type" + , error::LUMIERA_ERROR_WRONG_TYPE + ); } diff --git a/src/lib/wrapperptr.hpp b/src/lib/wrapperptr.hpp index 3cb4030ed..c2bd6a64c 100644 --- a/src/lib/wrapperptr.hpp +++ b/src/lib/wrapperptr.hpp @@ -58,8 +58,11 @@ namespace lumiera { * Later on, stored values can be retrieved either utilising static or dynamic casts; * error reporting is similar to the behaviour of dynamic_cast: when retrieving * a pointer, NULL is returned in case of mismatch. + * + * @deprecated not sure if this was a good idea anyway. Better re-think how to handle wrapped objects in visitation + * @todo really need to switch to the new lib::Variant and util::AccessCasted implementation ////////////////TICKET #450 */ - typedef lib::VariantO WrapperPtr; + typedef lib::VariantO WrapperPtr; diff --git a/tests/library/opaque-holder-test.cpp b/tests/library/opaque-holder-test.cpp index 017f215a2..da866abf2 100644 --- a/tests/library/opaque-holder-test.cpp +++ b/tests/library/opaque-holder-test.cpp @@ -41,8 +41,9 @@ namespace test{ using util::isnil; using util::for_each; using util::isSameObject; - using lumiera::error::LUMIERA_ERROR_INVALID; - using lumiera::error::LUMIERA_ERROR_ASSERTION; + using error::LUMIERA_ERROR_BOTTOM_VALUE; + using error::LUMIERA_ERROR_WRONG_TYPE; + using error::LUMIERA_ERROR_ASSERTION; using std::vector; using std::cout; @@ -216,7 +217,7 @@ namespace test{ oo.clear(); CHECK (!oo); CHECK (isnil(oo)); - VERIFY_ERROR (INVALID, oo.get() ); + VERIFY_ERROR (BOTTOM_VALUE, oo.get() ); #if false ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT VERIFY_ERROR (ASSERTION, oo->getIt() ); #endif ///////////////////////////////////////////////////////////////////////////////////////////////TICKET #537 : restore throwing ASSERT