From 83eb6976cd03225c16009c60d88974cd1df36991 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 20 Dec 2009 04:33:24 +0100 Subject: [PATCH] draft an universal val/ref wrapper, needed by TransformIter. Seemingly I've hit a nasty problem here, because PlacementIndex should return an Placement&, but this is being fetched after-the fact from within the iterator. --- src/lib/error.hpp | 1 + src/lib/meta/trait.hpp | 44 +------- src/lib/scoped-holder.hpp | 3 +- src/lib/wrapper.hpp | 160 ++++++++++++++++++++++++++++ tests/40components.tests | 4 + tests/lib/item-wrapper-test.cpp | 183 ++++++++++++++++++++++++++++++++ 6 files changed, 353 insertions(+), 42 deletions(-) create mode 100644 src/lib/wrapper.hpp create mode 100644 tests/lib/item-wrapper-test.cpp diff --git a/src/lib/error.hpp b/src/lib/error.hpp index b17d808f8..daf2cf242 100644 --- a/src/lib/error.hpp +++ b/src/lib/error.hpp @@ -124,6 +124,7 @@ namespace lumiera { /* generic error situations */ LUMIERA_ERROR_DECLARE (WRONG_TYPE); ///< runtime type mismatch LUMIERA_ERROR_DECLARE (ITER_EXHAUST); ///< end of sequence reached + LUMIERA_ERROR_DECLARE (BOTTOM_VALUE); ///< invalid or NIL value /** Macro for creating derived exception classes properly diff --git a/src/lib/meta/trait.hpp b/src/lib/meta/trait.hpp index 610a17e05..dce2f0030 100644 --- a/src/lib/meta/trait.hpp +++ b/src/lib/meta/trait.hpp @@ -26,6 +26,7 @@ #include "lib/meta/util.hpp" +#include "lib/wrapper.hpp" #include #include @@ -70,37 +71,6 @@ namespace typelist { }; - /** Extension to boost::reference_wrapper: - * Allows additionally to re-bind to another reference, - * almost like a pointer. For example this allows to cache - * results returned from an API call by reference. - * @warning potentially dangerous - */ - template - class AssignableRefWrapper - : public boost::reference_wrapper - { - typedef boost::reference_wrapper RefWrapper; - public: - - explicit AssignableRefWrapper(TY& ref) - : RefWrapper(ref) - { } - - AssignableRefWrapper& - operator= (RefWrapper const& o) - { - RefWrapper::operator= (o); - return *this; - } - - AssignableRefWrapper& - operator= (TY& newRef) - { - (*this) = RefWrapper(newRef); - return *this; - } - }; /** Type definition helper for pointer and reference types. @@ -125,23 +95,15 @@ namespace typelist { typedef pointer member_type; }; - template - struct RefTraits - { - typedef TY value_type; - typedef const TY* pointer; - typedef const TY& reference; - typedef pointer member_type; - }; - template struct RefTraits { typedef TY* pointer; typedef TY& reference; typedef TY value_type; - typedef AssignableRefWrapper member_type; + typedef lib::wrap::AssignableRefWrapper member_type; }; + //////////////////////////////////////////TODO: not needed 12/09 -- obsolete? useful? keep it? }} // namespace lumiera::typelist diff --git a/src/lib/scoped-holder.hpp b/src/lib/scoped-holder.hpp index 392a36d58..4e2c82627 100644 --- a/src/lib/scoped-holder.hpp +++ b/src/lib/scoped-holder.hpp @@ -145,7 +145,7 @@ namespace lib { char content_[sizeof(TY)]; char created_; - typedef ScopedHolder _ThisType; + typedef ScopedHolder _ThisType; ////TODO can get rid of this typedef, after using BoolCheckable static char must_be_empty (_ThisType const& ref) @@ -216,6 +216,7 @@ namespace lib { typedef char _ThisType::*unspecified_bool_type; + //////////////////////////////////TICKET #178 /** implicit conversion to "bool" */ operator unspecified_bool_type() const // never throws { diff --git a/src/lib/wrapper.hpp b/src/lib/wrapper.hpp new file mode 100644 index 000000000..095471c25 --- /dev/null +++ b/src/lib/wrapper.hpp @@ -0,0 +1,160 @@ +/* + WRAPPER.hpp - some smart wrapping and reference managing helper templates + + Copyright (C) Lumiera.org + 2009, 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 wrapper.hpp + ** Library implementation: smart-pointer variations, wrappers and managing holders. + ** This is (intended to become) a loose collection of the various small helper templates + ** for wrapping, containing, placing or handling a somewhat \em problematic other object. + ** Mostly these are implemented to suit a specific need and then factored out later on. + ** + ** @see lib::TransformIter + ** + */ + + +#ifndef LIB_WRAPPER_H +#define LIB_WRAPPER_H + +//#include "lib/bool-checkable.hpp" + +//#include + + +namespace lib { +namespace wrap { + +//using std::tr1::shared_ptr; +//using std::tr1::weak_ptr; + + + + /** + * Extension to boost::reference_wrapper: + * Allows additionally to re-bind to another reference, + * almost like a pointer. For example this allows to cache + * results returned from an API call by reference. + * @warning potentially dangerous + */ + template + class AssignableRefWrapper + : public boost::reference_wrapper + { + typedef boost::reference_wrapper RefWrapper; + public: + + explicit AssignableRefWrapper(TY& ref) + : RefWrapper(ref) + { } + + AssignableRefWrapper& + operator= (RefWrapper const& o) + { + RefWrapper::operator= (o); + return *this; + } + + AssignableRefWrapper& + operator= (TY& newRef) + { + (*this) = RefWrapper(newRef); + return *this; + } + }; + + + + namespace impl { + template + struct ItemWrapperStorage + { + char content_[sizeof(TY)]; + char created_; + + }; + } + + /** + * Universal value/ref wrapper behaving like a pointer. + * A copyable, assignable value object, not managing ownership. + * It can be default constructed and \c bool evaluated to detect + * an empty holder. The value is retrieved pointer-like, by + * explicit dereferentiation. (Contrast this to boost::ref, + * where the original reference is retrieved by conversion) + * + * The purpose of this template is to be able to remember + * pretty much any kind of value or pointer or reference, + * and to subsume this handling in a single template. + * An example would be to remember the value yielded + * by a function, without any further assumptions + * regarding this function. + */ + template + class ItemWrapper + : public BoolCheckable > + { + typedef typename impl::ItemWrapperStorage Item; + + Item item_; + + public: + ItemWrapper() + : item_() + { } + + explicit + ItemWrapper(TY& o) + : item_(o) + { } + + //note: using default copy ctor and assignment operator! + + template + ItemWrapper& + operator= (X const& something) ///< accept anything assignable to TY + { + item_ = something; + } + + /* == value access == */ + TY& + operator* () + { + return item_; + } + + bool + isValid () const + { + return item_.isValid(); + } + + void + reset () + { + item_.clear(); + } + }; + + + +}} // namespace lib::wrap +#endif diff --git a/tests/40components.tests b/tests/40components.tests index bcdfa0f3c..2101294bf 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -321,6 +321,10 @@ return: 0 END +PLANNED "inline val/ref wrapper" ItemWrapper_test < + + 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. + +* *****************************************************/ + + + +#include "lib/test/run.hpp" +#include "lib/test/test-helper.hpp" +#include "lib/util.hpp" + +#include "lib/wrapper.hpp" + +//#include +//#include +//#include +#include +#include + + + +namespace lib { +namespace test{ + + using ::Test; +// using boost::lexical_cast; + using util::isSameObject; +// using util::for_each; +// using util::isnil; +// using std::vector; + using std::string; +// using std::cout; +// using std::endl; + + + + namespace { // Test data + + ///////////TODO + + } // (END) Test data + + + + + + + + /******************************************************************************* + * @test use the ItemWrapper to define inline-storage holding values, + * pointers and references. Verify correct behaviour in each case, + * including assignment, empty check, invalid dereferentiation. + * + */ + class ItemWrapper_test : public Test + { + + + + virtual void + run (Arg) + { + UNIMPLEMENTED ("check ItemWrapper"); + + ulong ll (rand() % 1000); + string ss (randStr(50)); + const char* cp (ss.c_str()); + Tracker tt; + + verifyWrapper (ItemWrapper (ll), ll, -123); + verifyWrapper (ItemWrapper (ll), ll, 45678 ); + verifyWrapper (ItemWrapper (ll), ll, 0 ); + verifyWrapper (ItemWrapper (&ll), &ll, (ulong*) 0 ); + + verifyWrapper (ItemWrapper (ss), ss, "Lumiera"); + verifyWrapper (ItemWrapper (ss), ssl, string() ); + verifyWrapper (ItemWrapper (&ss), &ss, randStr(12)); + + verifyWrapper (ItemWrapper (tt), tt, Tracker()); + verifyWrapper (ItemWrapper (tt), tt, Tracker()); + verifyWrapper (ItemWrapper (&tt), &tt, (Tracker*) 0 ); + + verifyWrapper (ItemWrapper (cp), cp, "Lumiera"); + + verifyWrappedRef (); + } + + + template + void + verifyWrapper (ItemWrapper const& wrap, X const& val, X const& otherVal) + { + ASSERT (wrap); + + ItemWrapper copy1 (wrap); + ItemWrapper copy2; + ItemWrapper empty; + + ASSERT (copy1); + ASSERT (!copy2); + ASSERT (false == bool(empty)); + + ASSERT (wrap == copy1); + ASSERT (wrap != copy2); + ASSERT (wrap != empty); + + copy2 = copy1; + ASSERT (copy2); + ASSERT (wrap == copy2); + ASSERT (wrap != empty); + + copy2 = otherVal; + ASSERT (copy2); + ASSERT (wrap != copy2); + ASSERT (wrap != empty); + + ASSERT (val == *wrap); + ASSERT (val == *copy1); + ASSERT (val != *copy2); + VERIFY_ERROR (BOTTOM_VALUE, *empty ); + + ASSERT (otherVal == *copy2); + copy1 = copy2; + ASSERT (otherVal == *copy1); + ASSERT (otherVal == *copy2); + ASSERT (wrap != copy1); + ASSERT (wrap != copy2); + + copy1.clear(); + ASSERT (!copy1); + ASSERT (empty == copy1); + ASSERT (copy2 != copy1); + VERIFY_ERROR (BOTTOM_VALUE, *copy1 ); + }; + + + void + verifyWrappedRef () + { + int x = 5; + ItemWrapper refWrap; + ASSERT (!refWrap); + + refWrap = x; + ASSERT (refWrap); + ASSERT (5 == *refWrap); + ASSERT (x == *refWrap); + + *refWrap += 5; + ASSERT (x == 10); + + ItemWrapper ptrWrap (& *refWrap); + ASSERT (isSameObject (*ptrWrap, x)); + **ptrWrap += 13; + ASSERT (x == 23); + } + + + + }; + + LAUNCHER (ItemWrapper_test, "unit common"); + + +}} // namespace lib::test +