document the changed/new behaviour by unit test

This commit is contained in:
Fischlurch 2010-01-07 04:40:10 +01:00
parent 3525b77126
commit 5cc3af3009
3 changed files with 113 additions and 40 deletions

View file

@ -62,7 +62,8 @@ namespace meta {
/**
* Helper for type analysis:
* tries to extract a base type from various wrappers.
* Additionally allows to extract/deref the wrapped element
* Additionally allows to extract/deref the wrapped element.
* @warning strips away any const
*/
template<typename X>
struct Unwrap
@ -79,13 +80,13 @@ namespace meta {
template<typename X>
struct Unwrap<X*>
{
typedef X Type;
typedef typename boost::remove_cv<X>::type Type;
static X&
static Type&
extract (const X* ptr)
{
ASSERT (ptr);
return const_cast<X&> (*ptr);
return const_cast<Type&> (*ptr);
}
};
@ -152,7 +153,14 @@ namespace meta {
}
};
/** convenience shortcut: unwrapping free function */
/** convenience shortcut: unwrapping free function.
* @return reference to the bare element.
* @warning this function is dangerous: it strips away
* any managing smart-ptr and any const!
* You might even access and return a
* reference to an anonymous temporary.
*/
template<typename X>
typename Unwrap<X>::Type&
unwrap (X const& wrapped)
@ -162,6 +170,7 @@ namespace meta {
/** Helper for type analysis: tries to strip all kinds of type adornments */
template<typename X>
struct Strip
@ -175,6 +184,48 @@ namespace meta {
};
/** Type definition helper for pointer and reference types.
* Allows to create a member field and to get the basic type
* irrespective if the given type is plain, pointer or reference
*/
template<typename TY>
struct RefTraits
{
typedef TY* pointer;
typedef TY& reference;
typedef TY value_type;
typedef value_type member_type;
};
template<typename TY>
struct RefTraits<TY *>
{
typedef TY* pointer;
typedef TY& reference;
typedef TY value_type;
typedef pointer member_type;
};
template<typename TY>
struct RefTraits<TY &>
{
typedef TY* pointer;
typedef TY& reference;
typedef TY value_type;
typedef lib::wrapper::AssignableRefWrapper<TY> member_type;
};
//////////////////////////////////////////TODO: member_type not needed anymore 12/09 -- obsolete? useful? keep it?
/** Trait template for detecting if a type can be converted to string.
* For example, this allows to write specialisations with the help of
* boost::enable_if
@ -272,39 +323,5 @@ namespace meta {
};
/** Type definition helper for pointer and reference types.
* Allows to create a member field and to get the basic type
* irrespective if the given type is plain, pointer or reference
*/
template<typename TY>
struct RefTraits
{
typedef TY* pointer;
typedef TY& reference;
typedef TY value_type;
typedef value_type member_type;
};
template<typename TY>
struct RefTraits<TY *>
{
typedef TY* pointer;
typedef TY& reference;
typedef TY value_type;
typedef pointer member_type;
};
template<typename TY>
struct RefTraits<TY &>
{
typedef TY* pointer;
typedef TY& reference;
typedef TY value_type;
typedef lib::wrapper::AssignableRefWrapper<TY> member_type;
};
//////////////////////////////////////////TODO: member_type not needed anymore 12/09 -- obsolete? useful? keep it?
}} // namespace lib::meta
#endif

View file

@ -1034,6 +1034,9 @@ out: :60
out: :120
out: :180
out: sum=120
out: ---:wrapped_container_passing
out: :10:9:8:7:6:5:4:3:2:1
out: :-20:-21:-22:-23:-24:-25:-26:-27:-28:-29
out: ---:check_invoke_on_each
out: :0:1:2:3:4:5
out: :0$

View file

@ -159,6 +159,8 @@ namespace test {
ASSERT (60+int(NUM_ELMS) ==container[0]);
// changes got propagated through the iterator
check_wrapped_container_passing(container);
check_invoke_on_each ();
}
@ -237,7 +239,7 @@ namespace test {
* passing the iterator by value. This behaviour is correct, as
* an iterator is an reference-like object
*
* */
*/
template<typename CO>
void
check_ref_argument_bind (CO coll)
@ -413,6 +415,57 @@ namespace test {
// note: it seems not to be possible to create a binder, which takes the "*this"-Argument by ref
}
/** @test passing the collection to be iterated in various ways
* - anonymous temporary
* - smart pointer
* - pointer
* - const&
* @note We do modifications using a lambda expression with a
* side-effect. The container passed in is always modified,
* disregarding const! (In case of the anonymous temporary
* the modifications get discarded after reaching the end
* of the for_each expression
*/
void
check_wrapped_container_passing (VecI coll)
{
ANNOUNCE (wrapped_container_passing);
#define SHOW_CONTAINER for_each (coll, plainFunc); _NL_
// use a const reference to pass the container...
VecI const& passByConstRef (coll);
int counter = NUM_ELMS;
for_each (passByConstRef, _1_ = var(counter)-- );
SHOW_CONTAINER
// indeed got modifications into the original container!
ASSERT (0 == counter);
// passing anonymous temporary
for_each (buildTestNumberz(NUM_ELMS), _1_ = var(counter)-- );
// passing a smart-ptr managed copy
std::tr1::shared_ptr<VecI> bySmartPtr (new VecI (coll));
for_each (bySmartPtr, _1_ = var(counter)-- );
// both didn't influence the original container
SHOW_CONTAINER
ASSERT (-2*int(NUM_ELMS) == counter);
ASSERT (bySmartPtr->back() == counter+1);
// passing by pointer is also possible
const VecI * const passByConstPointer (&coll);
for_each (passByConstPointer, _1_ = var(counter)-- );
SHOW_CONTAINER
// ...and influences the original container
}
};