From 07f7837a7bebcfaa937f3cacadac4e193f0f314a Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 6 Nov 2010 21:23:35 +0100 Subject: [PATCH] draft behaviour of a optional/switchable object link --- src/lib/optional-ref.hpp | 87 ++++++++++++++++++ tests/lib/Makefile.am | 1 + tests/lib/optional-ref-test.cpp | 157 ++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 src/lib/optional-ref.hpp create mode 100644 tests/lib/optional-ref-test.cpp diff --git a/src/lib/optional-ref.hpp b/src/lib/optional-ref.hpp new file mode 100644 index 000000000..ff8b368c9 --- /dev/null +++ b/src/lib/optional-ref.hpp @@ -0,0 +1,87 @@ +/* + OPTIONAL-REF.hpp - optional and switchable reference + + Copyright (C) Lumiera.org + 2010, 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. + +*/ + + +#ifndef LIB_OPTIONAL_REF_H +#define LIB_OPTIONAL_REF_H + +#include "lib/error.hpp" +#include "lib/bool-checkable.hpp" +#include "lib/util.hpp" + +//#include +//#include +//#include + + +namespace lib { + + using lumiera::error::LUMIERA_ERROR_BOTTOM_VALUE; + + + /** + * Reference wrapper implemented as constant function, + * returning the (fixed) reference on invocation + */ + template + class ReturnRef + { + T& ref_; + + public: + ReturnRef(T& target) : ref_(target) { } + T& operator() () const { return ref_;} + }; + + template + ReturnRef + refFunction (T& target) + { + return ReturnRef (target); + } + + + + /** + * Optional or switchable link to an existing object. + * This reference wrapper normally behaves like a reference, + * but has the ability to be \em disabled. This disabled state + * is managed automatically by ctor and dtor, can be detected + * through \c bool check and -- contrary to a \c NULL pointer + * -- produces a real exception instead of crashing. + * @note \em not taking ownership of the pointee + */ + template + class OptionalRef + { + T* ref_; + + public: + OptionalRef() : ref_(0) { } + OptionalRef(T& target) : ref_(&target) { } + ~OptionalRef() { ref_ = 0; } + }; + + + +} // namespace lib +#endif diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index 27de09bc5..f8661006b 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -78,6 +78,7 @@ test_lib_SOURCES = \ $(testlib_srcdir)/null-value-test.cpp \ $(testlib_srcdir)/opaque-holder-test.cpp \ $(testlib_srcdir)/opaque-unchecked-buffer-test.cpp \ + $(testlib_srcdir)/optional-ref-test.cpp \ $(testlib_srcdir)/query/query-utils-test.cpp \ $(testlib_srcdir)/removefromsettest.cpp \ $(testlib_srcdir)/sanitised-identifier-test.cpp \ diff --git a/tests/lib/optional-ref-test.cpp b/tests/lib/optional-ref-test.cpp new file mode 100644 index 000000000..1fba48cec --- /dev/null +++ b/tests/lib/optional-ref-test.cpp @@ -0,0 +1,157 @@ +/* + OptionalRef(Test) - verify an optional and switchable object link + + Copyright (C) Lumiera.org + 2010, 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. + +* *****************************************************/ + + + +#include "lib/test/run.hpp" +#include "lib/test/test-helper.hpp" +//#include "lib/util.hpp" + +#include "lib/optional-ref.hpp" + +//#include +//#include +//#include +//#include +//#include + + + +namespace lib { +namespace test{ + + using ::Test; + using lib::test::randStr; + + using std::string; + + + + + + + + + + /******************************************************************************* + * @test verify a reference-like wrapper class, used to provide a switchable link + * to an already existing object. + * + * @see lib::OptionalRef + * @see lib::AutoRegistered usage example + */ + class OptionalRef_test : public Test + { + + + virtual void + run (Arg) + { + string s1 (randStr(50)); + string s2 (randStr(50)); + + typedef OptionalRef SRef; + + SRef r1; + CHECK (!r1); + VERIFY_ERROR (BOTTOM_VALUE, s1 = r1 ); + VERIFY_ERROR (BOTTOM_VALUE, s1 == r1 ); + VERIFY_ERROR (BOTTOM_VALUE, r1 == s1 ); + CHECK (!r1.points_to (s1)); + + r1.link_to (s1); + CHECK (r1); + CHECK (r1 == s1); + CHECK (s1 == r1); + CHECK (r1.points_to (s1)); + + SRef r2(s2); + CHECK (r2); + CHECK (r2 == s2); + CHECK (r2.points_to (s2)); + CHECK (!r2.points_to (s1)); + CHECK (!r1.points_to (s2)); + CHECK (r2 != r1); + CHECK (r1 != r2); + + r2.link_to (s1); + CHECK (r2); + CHECK (r2 == s1); + CHECK (r2 == r1); + CHECK (r1 == r2); + CHECK (r2.points_to (s1)); + CHECK (!r2.points_to (s2)); + + r2.clear(); + CHECK (!r2); + VERIFY_ERROR (BOTTOM_VALUE, s1 = r2 ); + VERIFY_ERROR (BOTTOM_VALUE, s1 == r2 ); + VERIFY_ERROR (BOTTOM_VALUE, r2 == s1 ); + VERIFY_ERROR (BOTTOM_VALUE, r2 == s2 ); + + CHECK (r1 != r2); // comparison with bottom ref allowed + CHECK (r2 != r1); + + //OptionalRef objects are copyable values + r2 = r1; + CHECK (r2); + CHECK (r2 == r1); + CHECK (r1 == r2); + CHECK (r2 == s1); + + r1.link_to (s2); + CHECK (r2 != r1); // but they are indeed independent instances + CHECK (r1 != r2); + CHECK (r2 == s1); + CHECK (r2 != s2); + CHECK (r1 == s2); + + SRef r3(r2); + CHECK (r3); + CHECK (r3 == r2); + CHECK (r2 == r3); + CHECK (r3 == s1); + + CHECK (r3 != r1); + CHECK (r1 != r3); + CHECK (r3 != s2); + + // access is secured even after destruction + CHECK (r3); + r1.~OptionalRef(); + CHECK (!r3); + VERIFY_ERROR (BOTTOM_VALUE, r3 == s1 ); + CHECK (r3 != r2); + + r2.clear(); + CHECK (!r2); + CHECK (r3 == r2); + CHECK (r2 == r3); + } + + }; + + LAUNCHER (OptionalRef_test, "unit common"); + + +}} // namespace lib::test +