document the changed/new behaviour by unit test
This commit is contained in:
parent
3525b77126
commit
5cc3af3009
3 changed files with 113 additions and 40 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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$
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue