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.
This commit is contained in:
Fischlurch 2009-12-20 04:33:24 +01:00
parent 4773305853
commit 83eb6976cd
6 changed files with 353 additions and 42 deletions

View file

@ -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

View file

@ -26,6 +26,7 @@
#include "lib/meta/util.hpp"
#include "lib/wrapper.hpp"
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
@ -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<typename TY>
class AssignableRefWrapper
: public boost::reference_wrapper<TY>
{
typedef boost::reference_wrapper<TY> 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<typename TY>
struct RefTraits<const TY *>
{
typedef TY value_type;
typedef const TY* pointer;
typedef const TY& reference;
typedef pointer member_type;
};
template<typename TY>
struct RefTraits<TY &>
{
typedef TY* pointer;
typedef TY& reference;
typedef TY value_type;
typedef AssignableRefWrapper<TY> member_type;
typedef lib::wrap::AssignableRefWrapper<TY> member_type;
};
//////////////////////////////////////////TODO: not needed 12/09 -- obsolete? useful? keep it?
}} // namespace lumiera::typelist

View file

@ -145,7 +145,7 @@ namespace lib {
char content_[sizeof(TY)];
char created_;
typedef ScopedHolder<TY> _ThisType;
typedef ScopedHolder<TY> _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
{

160
src/lib/wrapper.hpp Normal file
View file

@ -0,0 +1,160 @@
/*
WRAPPER.hpp - some smart wrapping and reference managing helper templates
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
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 <tr1/memory>
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<typename TY>
class AssignableRefWrapper
: public boost::reference_wrapper<TY>
{
typedef boost::reference_wrapper<TY> 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<typename TY>
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<typename TY>
class ItemWrapper
: public BoolCheckable<ItemWrapper<TY> >
{
typedef typename impl::ItemWrapperStorage<TY> Item;
Item item_;
public:
ItemWrapper()
: item_()
{ }
explicit
ItemWrapper(TY& o)
: item_(o)
{ }
//note: using default copy ctor and assignment operator!
template<typename X>
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

View file

@ -321,6 +321,10 @@ return: 0
END
PLANNED "inline val/ref wrapper" ItemWrapper_test <<END
END
TEST "Lumiera Iterator Concept" IterAdapter_test 20 <<END
out: ::20::19::18::17::16::15::14::13::12::11::10::9::8::7::6::5::4::3::2::1
out: ::0::1::2::3::4::5::6::7::8::9::10::11::12::13::14::15::16::17::18::19

View file

@ -0,0 +1,183 @@
/*
ItemWrapper(Test) - wrapping and holding arbitrary values, pointers and references
Copyright (C) Lumiera.org
2009, Hermann Vosseler <Ichthyostega@web.de>
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 <boost/lexical_cast.hpp>
//#include <iostream>
//#include <vector>
#include <cstdlib>
#include <string>
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<ulong> (ll), ll, -123);
verifyWrapper (ItemWrapper<ulong&> (ll), ll, 45678 );
verifyWrapper (ItemWrapper<ulong const&> (ll), ll, 0 );
verifyWrapper (ItemWrapper<ulong*> (&ll), &ll, (ulong*) 0 );
verifyWrapper (ItemWrapper<string> (ss), ss, "Lumiera");
verifyWrapper (ItemWrapper<string&> (ss), ssl, string() );
verifyWrapper (ItemWrapper<string*> (&ss), &ss, randStr(12));
verifyWrapper (ItemWrapper<Tracker> (tt), tt, Tracker());
verifyWrapper (ItemWrapper<Tracker&> (tt), tt, Tracker());
verifyWrapper (ItemWrapper<Tracker*> (&tt), &tt, (Tracker*) 0 );
verifyWrapper (ItemWrapper<const char*> (cp), cp, "Lumiera");
verifyWrappedRef ();
}
template<typename X>
void
verifyWrapper (ItemWrapper<X> const& wrap, X const& val, X const& otherVal)
{
ASSERT (wrap);
ItemWrapper<X> copy1 (wrap);
ItemWrapper<X> copy2;
ItemWrapper<X> 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<int&> refWrap;
ASSERT (!refWrap);
refWrap = x;
ASSERT (refWrap);
ASSERT (5 == *refWrap);
ASSERT (x == *refWrap);
*refWrap += 5;
ASSERT (x == 10);
ItemWrapper<int*> ptrWrap (& *refWrap);
ASSERT (isSameObject (*ptrWrap, x));
**ptrWrap += 13;
ASSERT (x == 23);
}
};
LAUNCHER (ItemWrapper_test, "unit common");
}} // namespace lib::test