From 69bf324a1eb88973f356cc129436b9805a3c476c Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 25 Apr 2015 19:26:59 +0200 Subject: [PATCH] extend to dereference pointer and take addresses ...since I consider that a comparatively safe convenience feature. Of course we *do perform* a NULL check and throw an exception. So now the actual casting or conversion functions are designed to work always on the same level of references or pointers, which means we can just use the standard conversions of the language. This has the nice effect of ruling out dangerous combinations (like taking a L-ref from a R-ref) automatically --- src/lib/access-casted.hpp | 61 ++++++++++-- tests/library/meta/access-casted-test.cpp | 107 +++++++++++++--------- 2 files changed, 114 insertions(+), 54 deletions(-) diff --git a/src/lib/access-casted.hpp b/src/lib/access-casted.hpp index 1880f3709..eff197e4b 100644 --- a/src/lib/access-casted.hpp +++ b/src/lib/access-casted.hpp @@ -54,25 +54,22 @@ namespace util { using std::remove_pointer; using std::remove_reference; + namespace error = lumiera::error; + + template + using PlainType = typename remove_pointer< + typename remove_reference::type>::type; template struct has_RTTI { - using PlainType = typename remove_pointer< - typename remove_reference::type>::type; - - static constexpr bool value = std::is_polymorphic::value; + static constexpr bool value = std::is_polymorphic>::value; }; template struct can_downcast { - 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; + static constexpr bool value = std::is_base_of, PlainType>::value; }; template @@ -88,6 +85,20 @@ namespace util { : std::is_convertible { }; + template + struct can_take_address + { + static constexpr bool value = !std::is_pointer::type>::value + && std::is_pointer::type>::value; + }; + + template + struct can_dereference + { + static constexpr bool value = !std::is_pointer::type>::value + && std::is_pointer::type>::value; + }; + template struct if_can_use_dynamic_downcast @@ -98,6 +109,16 @@ namespace util { struct if_can_use_conversion : std::enable_if< can_use_conversion::value, TAR> { }; + + template + struct if_can_take_address + : std::enable_if< can_take_address::value, TAR> + { }; + + template + struct if_can_dereference + : std::enable_if< can_dereference::value, TAR> + { }; @@ -121,6 +142,26 @@ namespace util { std::cerr << "convert-"<()<<" && ->"<()< (elem); } + + template + static typename if_can_take_address::type + access (SRC&& elem) + { + std::cerr << "address-"<()<<" && ->"<()<::access (&elem); + } + + template + static typename if_can_dereference::type + access (SRC&& elem) + { + std::cerr << "deref-"<()<<" && ->"<()<::access (*elem); + } }; diff --git a/tests/library/meta/access-casted-test.cpp b/tests/library/meta/access-casted-test.cpp index d1b4be725..931c52706 100644 --- a/tests/library/meta/access-casted-test.cpp +++ b/tests/library/meta/access-casted-test.cpp @@ -34,6 +34,9 @@ using std::move; using std::string; using std::ostream; using std::cout; +using std::endl; + +using lumiera::error::LUMIERA_ERROR_BOTTOM_VALUE; namespace util { @@ -94,61 +97,77 @@ namespace test { E* pE = &f; D* pDE = pE; - 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_downcast = " << can_downcast::value < = " << can_downcast::value < = " << can_downcast::value < = " << can_downcast::value < = " << can_downcast::value < = " << can_downcast::value < = " << can_downcast::value < = " << can_downcast::value << "\n"; - cout << "can_downcast = " << can_downcast::value << "\n"; + cout << "can_downcast = " << can_downcast::value < = " << can_downcast::value < = " << has_RTTI::value << "\n"; - cout << "has_RTTI = " << has_RTTI::value << "\n"; - cout << "has_RTTI = " << has_RTTI::value << "\n"; + cout << "has_RTTI = " << has_RTTI::value < = " << has_RTTI::value < = " << has_RTTI::value < = " << std::is_convertible::value << "\n"; - cout << "is_convertible = " << std::is_convertible::value << "\n"; + cout << "is_convertible = " << std::is_convertible::value < = " << std::is_convertible::value < = " << 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 < = " << can_use_conversion::value < = " << can_use_dynamic_downcast::value < = " << can_use_conversion::value < = " << 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 << "can_use_dynamic_downcast = " << can_use_dynamic_downcast::value < = " << can_use_conversion::value < = " << can_use_conversion::value < = " << can_use_dynamic_downcast::value <" << AccessCasted::access(d) <" << AccessCasted::access(rD) <" << AccessCasted::access(d) << "\n"; - cout << "Access(D& as D&) --->" << AccessCasted::access(rD) << "\n"; - cout << "Access(D as D) --->" << AccessCasted::access(d) << "\n"; - cout << "Access(D& as D) --->" << AccessCasted::access(rD) << "\n"; + cout << "=== build a value object ==="<" << AccessCasted::access(d) <" << AccessCasted::access(rD) <" << 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 D) --->" << AccessCasted::access(move(dd1)) <" << AccessCasted::access(d) <" << AccessCasted::access(rD) <" << AccessCasted::access(pD) <" << AccessCasted::access(pD) <" << AccessCasted::access(move(pdd1)) <::access(pNull)); + + cout << "=== work cases: actual conversions ==="<" << AccessCasted::access(rB) <" << AccessCasted::access(pD) <" << AccessCasted::access(pB) <" << AccessCasted::access(rpD) <" << AccessCasted::access(rpB) <" << 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 B&) --->" << AccessCasted::access(d) <" << AccessCasted::access(rD) <" << AccessCasted::access(rB) <" << AccessCasted::access(pD) <" << AccessCasted::access(pB) <" << AccessCasted::access(rpD) <" << AccessCasted::access(rpB) <" << 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 E&) --->" << AccessCasted::access(d) <" << AccessCasted::access(rE) <" << AccessCasted::access(pDE) <" << AccessCasted::access(pDE) <" << AccessCasted::access(pE) <