From 5cc3af3009ea1ceae311ef430d3482b8866d25e6 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 7 Jan 2010 04:40:10 +0100 Subject: [PATCH] document the changed/new behaviour by unit test --- src/lib/meta/trait.hpp | 95 +++++++++++++++++++-------------- tests/40components.tests | 3 ++ tests/lib/util-foreach-test.cpp | 55 ++++++++++++++++++- 3 files changed, 113 insertions(+), 40 deletions(-) diff --git a/src/lib/meta/trait.hpp b/src/lib/meta/trait.hpp index 2ead08e85..eb6d208ef 100644 --- a/src/lib/meta/trait.hpp +++ b/src/lib/meta/trait.hpp @@ -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 struct Unwrap @@ -79,13 +80,13 @@ namespace meta { template struct Unwrap { - typedef X Type; + typedef typename boost::remove_cv::type Type; - static X& + static Type& extract (const X* ptr) { ASSERT (ptr); - return const_cast (*ptr); + return const_cast (*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 Unwrap::Type& unwrap (X const& wrapped) @@ -162,6 +170,7 @@ namespace meta { + /** Helper for type analysis: tries to strip all kinds of type adornments */ template 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 + struct RefTraits + { + typedef TY* pointer; + typedef TY& reference; + typedef TY value_type; + typedef value_type member_type; + }; + + template + struct RefTraits + { + typedef TY* pointer; + typedef TY& reference; + typedef TY value_type; + typedef pointer member_type; + }; + + template + struct RefTraits + { + typedef TY* pointer; + typedef TY& reference; + typedef TY value_type; + typedef lib::wrapper::AssignableRefWrapper 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 - struct RefTraits - { - typedef TY* pointer; - typedef TY& reference; - typedef TY value_type; - typedef value_type member_type; - }; - - template - struct RefTraits - { - typedef TY* pointer; - typedef TY& reference; - typedef TY value_type; - typedef pointer member_type; - }; - - template - struct RefTraits - { - typedef TY* pointer; - typedef TY& reference; - typedef TY value_type; - typedef lib::wrapper::AssignableRefWrapper member_type; - }; - //////////////////////////////////////////TODO: member_type not needed anymore 12/09 -- obsolete? useful? keep it? - - }} // namespace lib::meta #endif diff --git a/tests/40components.tests b/tests/40components.tests index 847b9fa5c..6e078acaf 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -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$ diff --git a/tests/lib/util-foreach-test.cpp b/tests/lib/util-foreach-test.cpp index fbf9a8cb2..44ed644fd 100644 --- a/tests/lib/util-foreach-test.cpp +++ b/tests/lib/util-foreach-test.cpp @@ -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 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 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 + } + };