From 505903e71ea23d3e6d4b891289279f1bd050dc98 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 24 Apr 2015 01:54:54 +0200 Subject: [PATCH] Ticket #141 : move asside the old util::AccessCasted for rework ..existing code still uses the old version; will switch when the new one is ready --- src/lib/access-casted-o.hpp | 176 ++++++++++++++++++++++ src/lib/access-casted.hpp | 2 +- src/lib/opaque-holder.hpp | 2 +- src/lib/wrapperptr.hpp | 2 +- tests/15library.tests | 4 + tests/library/meta/access-casted-test.cpp | 132 +--------------- 6 files changed, 186 insertions(+), 132 deletions(-) create mode 100644 src/lib/access-casted-o.hpp diff --git a/src/lib/access-casted-o.hpp b/src/lib/access-casted-o.hpp new file mode 100644 index 000000000..4b8080ff2 --- /dev/null +++ b/src/lib/access-casted-o.hpp @@ -0,0 +1,176 @@ +/* + ACCESS-CASTED.hpp - util template to access a value using conversion or cast as appropriate + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/** @file access-casted-o.hpp + ** Helper for accessing a value, employing either conversion or downcast, + ** depending on the relation of the source type (type of the original value) + ** 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 + ** 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, + ** e.g. throwing an exception instead of creating a NULL value. + ** + ** @deprecated old obsolete version ///////////////////////////////////////////TICKET #738 clean-up access-casted, rewrite variant (4/2015) + ** @todo This is the obsoleted old version: It was excessively permissive, which + ** I've learned to view as a danger, since it encourages a sloppy programming style. + ** @see lumiera::WrapperPtr usage example to access a variant record + ** @see lib::InPlaceAnyHolder usage example to access a subclass in embedded storage + ** + */ + + +#ifndef UTIL_ACCESS_CASTED_O_H +#define UTIL_ACCESS_CASTED_O_H + +#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; + + 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 NullAccessor + { + typedef RET Ret; + + static RET access (...) { return ifEmpty(); } + static RET ifEmpty () { return EmptyVal::create(); } + }; + + template + struct AccessCasted : NullAccessor + { + using NullAccessor::access; + + template + static typename enable_if< use_dynamic_downcast, + TAR >::type + access (ELM& elem) + { + return dynamic_cast (elem); + } + + template + static typename enable_if< use_static_downcast, + TAR >::type + access (ELM& elem) + { + return static_cast (elem); + } + + template + static typename enable_if< use_conversion, + TAR >::type + access (ELM& elem) + { + return elem; + } + }; + + +} // namespace util +#endif diff --git a/src/lib/access-casted.hpp b/src/lib/access-casted.hpp index 039002d9a..ec7761dd6 100644 --- a/src/lib/access-casted.hpp +++ b/src/lib/access-casted.hpp @@ -33,7 +33,7 @@ ** type TAR. Alternatively, you may define an specialisation of EmptyVal, ** e.g. throwing an exception instead of creating a NULL value. ** - ** @todo ///////////////////////////////////////////TICKET #738 needs slight overhaul and clean-up + ** @todo WIP 4/2015 is being rewritten ///////////////////////////////////////////TICKET #738 needs slight overhaul and clean-up ** @see lumiera::WrapperPtr usage example to access a variant record ** @see lib::InPlaceAnyHolder usage example to access a subclass in embedded storage ** diff --git a/src/lib/opaque-holder.hpp b/src/lib/opaque-holder.hpp index bf484e817..5afe4fbd0 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.hpp" +#include "lib/access-casted-o.hpp" #include "lib/util.hpp" #include diff --git a/src/lib/wrapperptr.hpp b/src/lib/wrapperptr.hpp index 433d9f124..3cb4030ed 100644 --- a/src/lib/wrapperptr.hpp +++ b/src/lib/wrapperptr.hpp @@ -27,7 +27,7 @@ #include "lib/variant-o.hpp" -#include "lib/access-casted.hpp" +#include "lib/access-casted-o.hpp" #include "lib/meta/typelist.hpp" #include "proc/mobject/placement.hpp" diff --git a/tests/15library.tests b/tests/15library.tests index f3269c90e..40e2e7fb2 100644 --- a/tests/15library.tests +++ b/tests/15library.tests @@ -2,6 +2,10 @@ TESTING "Library Test Suite: basic and low-level components" ./test-suite --grou +TEST "casting or converting access helper" AccessCasted_test < diff --git a/tests/library/meta/access-casted-test.cpp b/tests/library/meta/access-casted-test.cpp index 26dca382d..6725b3051 100644 --- a/tests/library/meta/access-casted-test.cpp +++ b/tests/library/meta/access-casted-test.cpp @@ -23,145 +23,19 @@ #include "lib/test/run.hpp" - -#include -#include -#include -#include -#include -#include +#include "lib/access-casted.hpp" using std::string; using std::cout; using std::ostream; -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; - -namespace lib { -namespace meta { +namespace util { namespace test { - 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; - - 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 - ) - }; - }; - - - template - struct EmptyVal - { - static X create() - { - cout << " NULL() " << __PRETTY_FUNCTION__ <<"\n"; - return X(); - } - }; - template - struct EmptyVal - { - static X*& create() - { - cout << " NULL & " << __PRETTY_FUNCTION__ <<"\n"; - static X* null(0); - return null; - } - }; - - - template - struct NullAccessor - { - typedef RET Ret; - - static RET access (...) { return ifEmpty(); } - static RET ifEmpty () { return EmptyVal::create(); } - }; - - template - struct AccessCasted : NullAccessor - { - using NullAccessor::access; - - template - static typename enable_if< use_dynamic_downcast, TAR>::type - access (ELM& elem) - { - cout << " dynamic " << __PRETTY_FUNCTION__ <<"\n"; - return dynamic_cast (elem); - } - - template - static typename enable_if< use_static_downcast, TAR>::type - access (ELM& elem) - { - cout << " static " << __PRETTY_FUNCTION__ <<"\n"; - return static_cast (elem); - } - - template - static typename enable_if< use_conversion, TAR>::type - access (ELM& elem) - { - cout << " convert " << __PRETTY_FUNCTION__ <<"\n"; - return elem; - } - - }; @@ -273,4 +147,4 @@ namespace test { -}}} // namespace lib::meta::test +}} // namespace lib::meta::test