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:
parent
4773305853
commit
83eb6976cd
6 changed files with 353 additions and 42 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
160
src/lib/wrapper.hpp
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
183
tests/lib/item-wrapper-test.cpp
Normal file
183
tests/lib/item-wrapper-test.cpp
Normal 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
|
||||
|
||||
Loading…
Reference in a new issue