From b9aa8033c7e8a5fc7a1d533deb53f4c8a6ab137a Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 25 Apr 2015 18:51:49 +0200 Subject: [PATCH] Ticket #141: rewrite of AccessCasted -- cover the basics get the param handling straight, including rvalue references. We do not want to allow any dangerous combinations anymore. --- src/lib/access-casted.hpp | 136 +++++++--------------- tests/library/meta/access-casted-test.cpp | 87 +++++++------- 2 files changed, 93 insertions(+), 130 deletions(-) diff --git a/src/lib/access-casted.hpp b/src/lib/access-casted.hpp index ec7761dd6..1880f3709 100644 --- a/src/lib/access-casted.hpp +++ b/src/lib/access-casted.hpp @@ -43,132 +43,86 @@ #ifndef UTIL_ACCESS_CASTED_H #define UTIL_ACCESS_CASTED_H -#include -#include -#include -#include -#include -#include +#include "lib/error.hpp" + +#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 };}; + using std::remove_pointer; + using std::remove_reference; template struct has_RTTI { - typedef typename remove_pointer< - typename remove_reference::type>::type TPlain; + using PlainType = typename remove_pointer< + typename remove_reference::type>::type; - enum { value = is_polymorphic::value }; + static constexpr bool value = std::is_polymorphic::value; }; template - struct use_dynamic_downcast + struct can_downcast { - enum { value = can_cast::value - && has_RTTI::value - && has_RTTI::value - }; + using PlainSRC = typename remove_pointer< + typename remove_reference::type>::type; + using PlainTAR = typename remove_pointer< + typename remove_reference::type>::type; + + static constexpr bool value = std::is_base_of::value; }; template - struct use_static_downcast + struct can_use_dynamic_downcast { - enum { value = can_cast::value - && ( !has_RTTI::value - || !has_RTTI::value - ) - }; + static constexpr bool value = !std::is_convertible::value + && can_downcast::value + && has_RTTI::value; }; template - struct use_conversion - { - enum { value = is_convertible::value - && !( use_static_downcast::value - ||use_dynamic_downcast::value - ) - }; - }; + struct can_use_conversion + : std::is_convertible + { }; + template + struct if_can_use_dynamic_downcast + : std::enable_if< can_use_dynamic_downcast::value, TAR> + { }; - ////////////////////////////////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 if_can_use_conversion + : std::enable_if< can_use_conversion::value, TAR> + { }; + - - - - - template - struct NullAccessor - { - typedef RET Ret; - static RET access (...) { return ifEmpty(); } - static RET ifEmpty () { return EmptyVal::create(); } - }; - template - struct AccessCasted : NullAccessor + struct AccessCasted { - using NullAccessor::access; + typedef TAR Ret; - template - static typename enable_if< use_dynamic_downcast, - TAR >::type - access (ELM& elem) + template + static typename if_can_use_dynamic_downcast::type + access (SRC&& elem) { - return dynamic_cast (elem); + std::cerr << "downcast-"<()<<" && ->"<()< (std::forward(elem)); } - template - static typename enable_if< use_static_downcast, - TAR >::type - access (ELM& elem) + template + static typename if_can_use_conversion::type + access (SRC&& elem) { - return static_cast (elem); - } - - template - static typename enable_if< use_conversion, - TAR >::type - access (ELM& elem) - { - return elem; + std::cerr << "convert-"<()<<" && ->"<()< (elem); } }; - + } // namespace util #endif diff --git a/tests/library/meta/access-casted-test.cpp b/tests/library/meta/access-casted-test.cpp index 00cefb9cb..d1b4be725 100644 --- a/tests/library/meta/access-casted-test.cpp +++ b/tests/library/meta/access-casted-test.cpp @@ -26,10 +26,14 @@ #include "lib/test/test-helper.hpp" #include "lib/access-casted.hpp" +#include +#include +#include +using std::move; using std::string; -using std::cout; using std::ostream; +using std::cout; namespace util { @@ -90,56 +94,61 @@ namespace test { E* pE = &f; D* pDE = pE; - cout << "is_base_of = " << is_base_of::value << "\n"; - cout << "is_base_of = " << is_base_of::value << "\n"; - cout << "is_base_of = " << is_base_of::value << "\n"; + cout << "can_downcast = " << can_downcast::value << "\n"; + cout << "can_downcast = " << can_downcast::value << "\n"; + cout << "can_downcast = " << can_downcast::value << "\n"; + cout << "can_downcast = " << can_downcast::value << "\n"; + cout << "can_downcast = " << can_downcast::value << "\n"; + cout << "can_downcast = " << can_downcast::value << "\n"; + cout << "can_downcast = " << can_downcast::value << "\n"; - cout << "can_cast = " << can_cast::value << "\n"; - cout << "can_cast = " << can_cast::value << "\n"; - cout << "can_cast = " << can_cast::value << "\n"; - cout << "can_cast = " << can_cast::value << "\n"; - cout << "can_cast = " << can_cast::value << "\n"; - cout << "can_cast = " << can_cast::value << "\n"; - cout << "can_cast = " << can_cast::value << "\n"; - - cout << "can_cast = " << can_cast::value << "\n"; - cout << "can_cast = " << can_cast::value << "\n"; + cout << "can_downcast = " << can_downcast::value << "\n"; + cout << "can_downcast = " << can_downcast::value << "\n"; cout << "has_RTTI = " << has_RTTI::value << "\n"; cout << "has_RTTI = " << has_RTTI::value << "\n"; cout << "has_RTTI = " << has_RTTI::value << "\n"; + cout << "is_convertible = " << std::is_convertible::value << "\n"; + cout << "is_convertible = " << std::is_convertible::value << "\n"; - cout << "use_dynamic_downcast = " << use_dynamic_downcast::value << "\n"; - cout << "use_static_downcast = " << use_static_downcast::value << "\n"; - cout << "use_conversion = " << use_conversion::value << "\n"; - cout << "use_static_downcast = " << use_static_downcast::value << "\n"; - cout << "use_static_downcast = " << use_static_downcast::value << "\n"; - cout << "use_dynamic_downcast = " << use_dynamic_downcast::value << "\n"; + cout << "can_use_dynamic_downcast = " << can_use_dynamic_downcast::value << "\n"; + cout << "can_use_conversion = " << can_use_conversion::value << "\n"; + cout << "can_use_dynamic_downcast = " << can_use_dynamic_downcast::value << "\n"; + cout << "can_use_conversion = " << can_use_conversion::value << "\n"; + + cout << "can_use_dynamic_downcast = " << can_use_dynamic_downcast::value << "\n"; + cout << "can_use_conversion = " << can_use_conversion::value << "\n"; + cout << "can_use_conversion = " << can_use_conversion::value << "\n"; + cout << "can_use_dynamic_downcast = " << can_use_dynamic_downcast::value << "\n"; cout << "Access(D as D&) --->" << AccessCasted::access(d) << "\n"; cout << "Access(D& as D&) --->" << AccessCasted::access(rD) << "\n"; - cout << "Access(B& as D&) --->" << AccessCasted::access(rB) << "\n"; - cout << "Access(D* as D*) --->" << AccessCasted::access(pD) << "\n"; - cout << "Access(B* as D*) --->" << AccessCasted::access(pB) << "\n"; - cout << "Access(D*& as D*&) --->" << AccessCasted::access(rpD) << "\n"; - cout << "Access(B*& as D*&) --->" << AccessCasted::access(rpB) << "\n"; - - cout << "Access(D as B&) --->" << AccessCasted::access(d) << "\n"; - cout << "Access(D& as B&) --->" << AccessCasted::access(rD) << "\n"; - cout << "Access(B& as B&) --->" << AccessCasted::access(rB) << "\n"; - cout << "Access(D* as B*) --->" << AccessCasted::access(pD) << "\n"; - cout << "Access(B* as B*) --->" << AccessCasted::access(pB) << "\n"; - cout << "Access(D*& as B*&) --->" << AccessCasted::access(rpD) << "\n"; - cout << "Access(B*& as B*&) --->" << AccessCasted::access(rpB) << "\n"; - - cout << "Access(D as E&) --->" << AccessCasted::access(d) << "\n"; - cout << "Access(E& as F&) --->" << AccessCasted::access(rE) << "\n"; - cout << "Access(D(E)* as E*) --->" << AccessCasted::access(pDE) << "\n"; - cout << "Access(D(E)* as F*) --->" << AccessCasted::access(pDE) << "\n"; - cout << "Access(E* as F*) --->" << AccessCasted::access(pE) << "\n"; + cout << "Access(D as D) --->" << AccessCasted::access(d) << "\n"; + cout << "Access(D& as D) --->" << AccessCasted::access(rD) << "\n"; + D dd1(d); + cout << "Access(D&& as D) --->" << AccessCasted::access(move(dd1)) << "\n"; +// cout << "Access(B& as D&) --->" << AccessCasted::access(rB) << "\n"; +// cout << "Access(D* as D*) --->" << AccessCasted::access(pD) << "\n"; +// cout << "Access(B* as D*) --->" << AccessCasted::access(pB) << "\n"; +// cout << "Access(D*& as D*&) --->" << AccessCasted::access(rpD) << "\n"; +// cout << "Access(B*& as D*&) --->" << AccessCasted::access(rpB) << "\n"; +// +// cout << "Access(D as B&) --->" << AccessCasted::access(d) << "\n"; +// cout << "Access(D& as B&) --->" << AccessCasted::access(rD) << "\n"; +// cout << "Access(B& as B&) --->" << AccessCasted::access(rB) << "\n"; +// cout << "Access(D* as B*) --->" << AccessCasted::access(pD) << "\n"; +// cout << "Access(B* as B*) --->" << AccessCasted::access(pB) << "\n"; +// cout << "Access(D*& as B*&) --->" << AccessCasted::access(rpD) << "\n"; +// cout << "Access(B*& as B*&) --->" << AccessCasted::access(rpB) << "\n"; +// +// cout << "Access(D as E&) --->" << AccessCasted::access(d) << "\n"; +// cout << "Access(E& as F&) --->" << AccessCasted::access(rE) << "\n"; +// cout << "Access(D(E)* as E*) --->" << AccessCasted::access(pDE) << "\n"; +// cout << "Access(D(E)* as F*) --->" << AccessCasted::access(pDE) << "\n"; +// cout << "Access(E* as F*) --->" << AccessCasted::access(pE) << "\n"; } };