Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r76620 - sandbox/closure/libs/local_function/example
From: lorcaminiti_at_[hidden]
Date: 2012-01-21 13:25:26


Author: lcaminiti
Date: 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
New Revision: 76620
URL: http://svn.boost.org/trac/boost/changeset/76620

Log:
Examples and tests.
Added:
   sandbox/closure/libs/local_function/example/const_block.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/const_block.hpp (contents, props changed)
   sandbox/closure/libs/local_function/example/const_block_ok.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/gcc_access.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/gcc_square.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/gcc_store.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/impl_factorial.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/impl_pp_keyword.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/impl_tparam_tricks.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/n2529_this.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/n2550_find_if.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/scope_exit.cpp (contents, props changed)
   sandbox/closure/libs/local_function/example/scope_exit.hpp (contents, props changed)

Added: sandbox/closure/libs/local_function/example/const_block.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/const_block.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,14 @@
+
+#include "const_block.hpp"
+#include <cassert>
+
+int main(void) {
+ //[example_const_block
+ int x = 1, y = 2;
+ CONST_BLOCK(x, y) { // Constant block.
+ assert(x = y); // Compiler error.
+ } CONST_BLOCK_END
+ //]
+ return 0;
+}
+

Added: sandbox/closure/libs/local_function/example/const_block.hpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/const_block.hpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,49 @@
+
+#ifndef CONST_BLOCK_HPP_
+#define CONST_BLOCK_HPP_
+
+#include <boost/local_function.hpp>
+#include <boost/local_function/detail/preprocessor/void_list.hpp>
+#include <boost/local_function/detail/preprocessor/line_counter.hpp>
+#include <boost/preprocessor/list/for_each_i.hpp>
+#include <boost/preprocessor/list/adt.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/control/iif.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <cassert>
+
+// PRIVATE //
+
+#define CONST_BLOCK_BIND_(r, unused, i, var) \
+ BOOST_PP_COMMA_IF(i) const bind& var
+
+#define CONST_BLOCK_(list) \
+ void BOOST_LOCAL_FUNCTION( \
+ BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(list), \
+ void BOOST_PP_TUPLE_EAT(3) \
+ , \
+ BOOST_PP_LIST_FOR_EACH_I \
+ )(CONST_BLOCK_BIND_, ~, list) \
+ )
+
+#define CONST_BLOCK_END_(id) \
+ BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(const_assert_, id)) \
+ BOOST_PP_CAT(const_assert_, id)(); /* call local function immediately */
+
+// PUBLIC //
+
+// Arguments `void | var1, var2, ... | (var1) (var2) ...`.
+#ifdef BOOST_NO_VARIADIC_MACROS
+# define CONST_BLOCK(void_or_seq) \
+ CONST_BLOCK_(BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(void_or_seq))
+#else
+# define CONST_BLOCK(...) \
+ CONST_BLOCK_(BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(__VA_ARGS__))
+#endif
+
+#define CONST_BLOCK_END \
+ CONST_BLOCK_END_(BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER)
+
+#endif // #include guard
+

Added: sandbox/closure/libs/local_function/example/const_block_ok.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/const_block_ok.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,12 @@
+
+#include "const_block.hpp"
+#include <cassert>
+
+int main(void) {
+ int x = 0, y = 0;
+ CONST_BLOCK(x, y) {
+ assert(x == y);
+ } CONST_BLOCK_END
+ return 0;
+}
+

Added: sandbox/closure/libs/local_function/example/gcc_access.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/gcc_access.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,22 @@
+
+// Copyright (C) 2009-2011 Lorenzo Caminiti
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a
+// copy at http://www.boost.org/LICENSE_1_0.txt).
+
+#include <boost/local_function.hpp>
+#define BOOST_TEST_MODULE ExampleGccAccess
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( example_gcc_access ) {
+ int nums[] = {1, 2, 3};
+ int offset = -1;
+ int BOOST_LOCAL_FUNCTION(const bind offset, int* array, int index) {
+ return array[index + offset];
+ } BOOST_LOCAL_FUNCTION_NAME(access)
+
+ BOOST_CHECK( access(nums, 1) == 1 );
+ BOOST_CHECK( access(nums, 2) == 2 );
+ BOOST_CHECK( access(nums, 3) == 3 );
+}
+

Added: sandbox/closure/libs/local_function/example/gcc_square.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/gcc_square.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,22 @@
+
+// Copyright (C) 2009-2011 Lorenzo Caminiti
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a
+// copy at http://www.boost.org/LICENSE_1_0.txt).
+
+#include <boost/local_function.hpp>
+#define BOOST_TEST_MODULE ExampleGccSquare
+#include <boost/test/unit_test.hpp>
+
+double add_square(double a, double b) {
+ double BOOST_LOCAL_FUNCTION(double z) {
+ return z * z;
+ } BOOST_LOCAL_FUNCTION_NAME(square)
+
+ return square(a) + square(b);
+}
+
+BOOST_AUTO_TEST_CASE( example_gcc_square ) {
+ BOOST_CHECK( add_square(2.0, 4.0) == 20.0 );
+}
+

Added: sandbox/closure/libs/local_function/example/gcc_store.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/gcc_store.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,32 @@
+
+// Copyright (C) 2009-2011 Lorenzo Caminiti
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a
+// copy at http://www.boost.org/LICENSE_1_0.txt).
+
+#include <boost/local_function.hpp>
+#include <boost/function.hpp>
+#define BOOST_TEST_MODULE ExampleGccStore
+#include <boost/test/unit_test.hpp>
+
+void intermediate(boost::function<void (int, int)> store_func, int size) {
+ store_func(size - 1, -1);
+}
+
+void hack(int* array, int size) {
+ void BOOST_LOCAL_FUNCTION(bind array, int index, int value) {
+ array[index] = value;
+ } BOOST_LOCAL_FUNCTION_NAME(store)
+
+ intermediate(store, size);
+}
+
+BOOST_AUTO_TEST_CASE( example_gcc_store ) {
+ int nums[] = {1, 2, 3};
+ hack(nums, 3);
+
+ BOOST_CHECK( nums[0] == 1 );
+ BOOST_CHECK( nums[1] == 2 );
+ BOOST_CHECK( nums[2] == -1 );
+}
+

Added: sandbox/closure/libs/local_function/example/impl_factorial.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/impl_factorial.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,184 @@
+
+// Copyright (C) 2009-2011 Lorenzo Caminiti
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a
+// copy at http://www.boost.org/LICENSE_1_0.txt).
+
+//[example_impl_factorial
+#include <boost/local/function.hpp>
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+#include <vector>
+#include <string>
+
+struct calculator {
+ std::ostringstream output;
+
+ void factorials(const std::vector<int>& nums,
+ const std::string& separator = " ") {
+
+ int // The local function result type (just before the `BOOST_LOCAL_FUNCTION_PARAMS` macro).
+
+ // *BEGIN* The macro
+ // BOOST_LOCAL_FUNCTION_PARAMS( (int n) (bool recursion)(default false)
+ // (const bind& separator) (bind this) )
+ // expands (at line 21) to:
+
+ // DEDUCE RESULT TYPE
+ // Long name `ERROR_...` gives meaningful compiler-error message if programmers forget result type before the macro.
+ (*ERROR_missing_result_type_before_the_local_function_parameter_macro_id21)();
+ // Use Boost.ScopeExit type deduction technique (tagging, wrapping, struct, etc) so to work on all compilers (specifically, some GCC version give internal errors otherwise).
+ typedef void (*boost_local_auxXdeduce_result_tag21)( int ERROR_missing_result_type_before_the_local_function_parameter_macro_id21);
+ typedef BOOST_TYPEOF(boost::scope_exit::aux::wrap( boost::scope_exit::aux::deref( ERROR_missing_result_type_before_the_local_function_parameter_macro_id21, (boost_local_auxXdeduce_result_tag21)0))) boost_local_auxXdeduce_result_wrap21;
+ typedef boost_local_auxXdeduce_result_wrap21::type boost_local_auxXdeduce_result_capture21;
+ struct boost_local_auxXdeduce_result_params21 {
+ typedef boost_local_auxXdeduce_result_capture21 function_ptr_type;
+ };
+ typedef boost::remove_pointer< boost_local_auxXdeduce_result_params21::function_ptr_type >::type boost_local_auxXdeduce_result_function_type21;
+ typedef boost::function_traits< boost_local_auxXdeduce_result_function_type21>::result_type boost_local_auxXresult_type21;
+
+ // HANDLE BOUND PARAMETERS
+ // Deduce object `this` type (using technique from Boost.ScopeExit patch to support `this`).
+#if BOOST_WORKAROUND(BOOST_MSVC,>=1300)
+ enum { boost_se_thistype_index_21 = sizeof(*boost::scope_exit::msvc_typeof_this::encode_start(this)) };
+ typedef boost::scope_exit::msvc_typeof_this::msvc_typeid_wrapper<boost_se_thistype_index_21>::type se_this_type21;
+#else
+ typedef BOOST_TYPEOF(this) se_this_type21;
+#endif
+ // Deduce other `& separator` type (using Boost.ScopeExit techniques).
+ typedef void (*boost_se_tag_0_21)(int & separator);
+ typedef BOOST_TYPEOF(boost::scope_exit::aux::wrap( boost::scope_exit::aux::deref(& separator, (boost_se_tag_0_21)0))) boost_se_wrapped_t_0_21;
+ typedef boost_se_wrapped_t_0_21::type boost_se_capture_t_0_21;
+ // Store bound parameter values and references.
+ struct boost_se_params_t_21 {
+ se_this_type21 se_this;
+ typedef boost_se_capture_t_0_21 boost_se_param_t_0_21;
+ boost::scope_exit::aux::member< boost_se_param_t_0_21, boost_se_tag_0_21 > boost_se_param_0_21;
+ } boost_local_auxXparams21 = {
+ this ,
+#ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
+ {
+#endif
+ boost::scope_exit::aux::deref(& separator, (boost_se_tag_0_21)0)
+#ifdef BOOST_SCOPE_EXIT_AUX_TPL_WORKAROUND
+ }
+#endif
+ };
+ // Use variable name `...args` without line number to hold bound parameter values (so the same variable name can be used by the `NAME` macro even if it expands on a different line number).
+ // The `declared<>` template makes sure that the variable `...args` is not declared multiple times in the same context (if the variable is already declared, this template expand to a no-operation).
+ boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve< sizeof(boost_local_auxXargs) >::cmp1<0>::cmp2 > boost_local_auxXargs;
+ boost_local_auxXargs.value = &boost_local_auxXparams21;
+
+ // LOCAL FUNCTOR
+ class boost_local_auxXfunctor21 {
+ typedef boost_local_auxXresult_type21 (boost_local_auxXfunction_type) ( int n , bool recursion );
+ typedef ::boost::local::aux::function< boost_local_auxXfunction_type, 1 > boost_local_auxXfunctor_type;
+ typedef ::boost::add_const< boost_se_params_t_21:: boost_se_param_t_0_21 >::type & separatorXboost_local_auxXtypeof_type ;
+ typedef se_this_type21 thisXboost_local_auxXtypeof_type ;
+ public:
+ // Take a generic pointer so it can be invoked by the `NAME` macro even if it expands on a different line number.
+ inline explicit boost_local_auxXfunctor21( void* bindings) :
+ boost_local_auxXbind_this( static_cast< boost_se_params_t_21* >( bindings)-> se_this )
+ , boost_local_auxXbind0 ( static_cast< boost_se_params_t_21* >( bindings)-> boost_se_param_0_21.value )
+ { }
+
+ // Implement `operator()` for all parameters and any combination of default parameter.
+ inline boost_local_auxXresult_type21 operator()(
+ ::boost::call_traits< ::boost::function_traits< boost_local_auxXfunction_type>::arg1_type>::param_type arg1
+ , ::boost::call_traits< ::boost::function_traits< boost_local_auxXfunction_type>::arg2_type>::param_type arg2
+ ) const {
+ return boost_local_auxXbody( boost_local_auxXbind0 , boost_local_auxXbind_this , arg1 , arg2 );
+ }
+ inline boost_local_auxXresult_type21 operator()(
+ ::boost::call_traits< ::boost::function_traits< boost_local_auxXfunction_type>::arg1_type>::param_type arg1
+ ) const {
+ return boost_local_auxXbody( boost_local_auxXbind0 , boost_local_auxXbind_this , arg1 );
+ }
+
+ // "Casting functor trick" to pass this local class as template parameter.
+ inline static boost_local_auxXresult_type21 boost_local_auxXcall0(
+ void* object
+ , ::boost::call_traits< ::boost::function_traits< boost_local_auxXfunction_type>::arg1_type>::param_type arg1
+ , ::boost::call_traits< ::boost::function_traits< boost_local_auxXfunction_type>::arg2_type>::param_type arg2
+ ) {
+ return static_cast< boost_local_auxXfunctor21* >( object)->operator()( arg1 , arg2 );
+ }
+ inline static boost_local_auxXresult_type21 boost_local_auxXcall1(
+ void* object
+ , ::boost::call_traits< ::boost::function_traits< boost_local_auxXfunction_type>::arg1_type>::param_type arg1
+ ) {
+ return static_cast< boost_local_auxXfunctor21* >( object)->operator()( arg1 );
+ }
+ inline static void boost_local_auxXinit_call( void* object, boost_local_auxXfunctor_type& functor) {
+ functor.boost_local_auxXinit_call(object, &boost_local_auxXcall0 , &boost_local_auxXcall1 );
+ }
+
+ private:
+ // Hold bound variables (by value and reference).
+ se_this_type21 & boost_local_auxXbind_this ;
+ ::boost::add_const< boost_se_params_t_21:: boost_se_param_t_0_21 >::type & boost_local_auxXbind0 ;
+ // This same declaration is first made at global scope in one of the library header files. This declaration needs to be repeated here so it is also visible from within the local function body to allow for nesting local function into one another.
+ boost::scope_exit::aux::undeclared boost_local_auxXargs;
+
+ // The local function body.
+ inline boost_local_auxXresult_type21 boost_local_auxXbody(
+ ::boost::add_const< boost_se_params_t_21:: boost_se_param_t_0_21 >::type & separator
+ , se_this_type21 const this_ // Use special name `this_` instead of `this` here.
+ // Specify default parameter values here.
+ , int n , bool recursion = false
+ ) const
+
+ // *END* The expansion of `BOOST_LOCAL_FUNCTION_PARAMS` ends here.
+
+ // *BEGIN* The local function body code `{ ... }` as specified by the programmers:
+
+ {
+
+ int result = 0;
+
+ if (n < 2 ) result = 1;
+ else result = n * factorial(n - 1, true); // Recursive call.
+
+ if (!recursion) this_->output << result << separator;
+ return result;
+ }
+
+ // *END* The local function body `{ ... }` ends here.
+
+ // *BEGIN* The macro `BOOST_LOCAL_FUNCTION_NAME(recursive factorial)` expands to:
+
+ public:
+ // Member variable named after the local function so the body can recursively call the local function (this must be defined here because the local function name was not known before). This must be public because it is also used to deduce the local function functor type later when when declaring the actual local function object.
+ boost_local_auxXfunctor_type factorial;
+ // Initializes the local functor member variable (this cannot be done directly within the constructor because the local function name is not known when the constructor code is expanded by the `PARAMS` macro).
+ inline void boost_local_auxXinit_recursion( boost_local_auxXfunctor_type& functor) {
+ factorial = functor;
+ }
+ // Declare the local class object -- which cannot be passed as template parameter (because it is a local class). It uses the variable with the generic `...args` name to pass the bound parameter values and references (so this variable name must not contain the line number because it is used by different macros expanding on different lines).
+ } boost_local_auxXfactorial(boost_local_auxXargs.value);
+ // Declare the actual local function object with the local function name -- which can be passed as template parameter (because it is a `boost::local::function` functor and not a local class).
+ BOOST_TYPEOF(boost_local_auxXfactorial. factorial) factorial;
+ // Initializes casting functor to pass local function as template parameter.
+ boost_local_auxXfactorial.boost_local_auxXinit_call( &boost_local_auxXfactorial, factorial);
+ // Initializes functor for recursion.
+ boost_local_auxXfactorial.boost_local_auxXinit_recursion( factorial);
+
+ // *END* The expansion of `BOOST_LOCAL_FUNCTION_NAME` ends here.
+
+ std::for_each(nums.begin(), nums.end(), factorial);
+ }
+};
+
+int main() {
+ std::vector<int> v(3);
+ v[0] = 1; v[1] = 4; v[2] = 7;
+
+ calculator calc;
+ calc.factorials(v);
+ std::cout << calc.output.str() << std::endl;
+
+ return 0;
+}
+//]
+

Added: sandbox/closure/libs/local_function/example/impl_pp_keyword.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/impl_pp_keyword.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,27 @@
+
+// Copyright (C) 2009-2011 Lorenzo Caminiti
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a
+// copy at http://www.boost.org/LICENSE_1_0.txt).
+
+//[example_impl_pp_keyword
+#include <boost/local_function/detail/preprocessor/keyword/thisunderscore.hpp>
+#include <boost/local_function/detail/preprocessor/keyword/const.hpp>
+#include <boost/local_function/detail/preprocessor/keyword/bind.hpp>
+#define BOOST_TEST_MODULE ExampleImplPpKeyword
+#include <boost/test/unit_test.hpp>
+
+// Expand to 1 if space-separated tokens end with `this_`, 0 otherwise.
+#define HAS_THIS_(tokens) \
+ BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_THISUNDERSCORE_BACK( \
+ BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_BIND_REMOVE_FRONT( \
+ BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_CONST_REMOVE_FRONT( \
+ tokens \
+ )))
+
+BOOST_AUTO_TEST_CASE( example_impl_pp_keyword ) {
+ BOOST_CHECK( HAS_THIS_(const bind this_) == 1 );
+ BOOST_CHECK( HAS_THIS_(const bind& x) == 0 );
+}
+//]
+

Added: sandbox/closure/libs/local_function/example/impl_tparam_tricks.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/impl_tparam_tricks.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,73 @@
+
+// Copyright (C) 2009-2011 Lorenzo Caminiti
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a
+// copy at http://www.boost.org/LICENSE_1_0.txt).
+
+// Tricks to "pass" a local class as a template parameter.
+
+//[example_impl_tparam_tricks
+#define BOOST_TEST_MODULE ExampleTparamTricks
+#include <boost/test/unit_test.hpp>
+#include <vector>
+#include <algorithm>
+
+// Casting functor trick.
+struct casting_func {
+ explicit casting_func(void* obj, void (*call)(void*, const int&)):
+ obj_(obj), call_(call) {}
+ // Unfortunately, function pointer call is not inlined.
+ inline void operator()(const int& num) { call_(obj_, num); }
+private:
+ void* obj_;
+ void (*call_)(void*, const int&);
+};
+
+// Virtual functor trick.
+struct virtual_func {
+ struct interface {
+ // Unfortunately, virtual function call is not inlined.
+ inline virtual void operator()(const int&) {}
+ };
+ explicit virtual_func(interface& func): func_(&func) {}
+ inline void operator()(const int& num) { (*func_)(num); }
+private:
+ interface* func_;
+};
+
+BOOST_AUTO_TEST_CASE( example_tparam_tricks ) {
+ int sum = 0, factor = 10;
+
+ // Local class for local function.
+ struct local_add: virtual_func::interface {
+ explicit local_add(int& _sum, const int& _factor):
+ sum_(_sum), factor_(_factor) {}
+ inline void operator()(const int& num) {
+ body(sum_, factor_, num);
+ }
+ inline static void call(
+ void* obj, const int& num) {
+ local_add* self = static_cast<local_add*>(obj);
+ self->body(self->sum_, self->factor_, num);
+ }
+ private:
+ int& sum_;
+ const int& factor_;
+ inline void body(int& sum, const int& factor, const int& num) {
+ sum += factor * num;
+ }
+ } add_local(sum, factor);
+ casting_func add_casting(&add_local, &local_add::call);
+ virtual_func add_virtual(add_local);
+
+ std::vector<int> v(10);
+ std::fill(v.begin(), v.end(), 1);
+
+// std::for_each(v.begin(), v.end(), add_local); // Error but OK on C++11.
+ std::for_each(v.begin(), v.end(), add_casting); // OK.
+ std::for_each(v.begin(), v.end(), add_virtual); // OK.
+
+ BOOST_CHECK( sum == 200 );
+}
+//]
+

Added: sandbox/closure/libs/local_function/example/n2529_this.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/n2529_this.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,41 @@
+
+// Copyright (C) 2009-2011 Lorenzo Caminiti
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a
+// copy at http://www.boost.org/LICENSE_1_0.txt).
+
+#include <boost/local_function.hpp>
+#define BOOST_TEST_MODULE ExampleN2529This
+#include <boost/test/unit_test.hpp>
+#include <vector>
+#include <algorithm>
+
+struct v {
+ std::vector<int> nums;
+
+ v(const std::vector<int>& numbers): nums(numbers) {}
+
+ void change_sign_all(const std::vector<int>& indices) {
+ void BOOST_LOCAL_FUNCTION(bind this_, int i) { // Bind object `this`.
+ this_->nums.at(i) = -this_->nums.at(i);
+ } BOOST_LOCAL_FUNCTION_NAME(complement)
+
+ std::for_each(indices.begin(), indices.end(), complement);
+ }
+};
+
+BOOST_AUTO_TEST_CASE( example_n2529_this ) {
+ std::vector<int> n(3);
+ n[0] = 1; n[1] = 2; n[2] = 3;
+
+ std::vector<int> i(2);
+ i[0] = 0; i[1] = 2; // Will change n[0] and n[2] but not n[1].
+
+ v vn(n);
+ vn.change_sign_all(i);
+
+ BOOST_CHECK( vn.nums.at(0) == -1 );
+ BOOST_CHECK( vn.nums.at(1) == 2 );
+ BOOST_CHECK( vn.nums.at(2) == -3 );
+}
+

Added: sandbox/closure/libs/local_function/example/n2550_find_if.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/n2550_find_if.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,40 @@
+
+// Copyright (C) 2009-2011 Lorenzo Caminiti
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a
+// copy at http://www.boost.org/LICENSE_1_0.txt).
+
+#include <boost/local_function.hpp>
+#define BOOST_TEST_MODULE ExampleN2550FindIf
+#include <boost/test/unit_test.hpp>
+#include <vector>
+#include <algorithm>
+
+struct employee {
+ int salary;
+ explicit employee(const int& a_salary): salary(a_salary) {}
+};
+
+BOOST_AUTO_TEST_CASE( example_n2550_find_if ) {
+ std::vector<employee> employees;
+ employees.push_back(employee( 85000));
+ employees.push_back(employee(100000));
+ employees.push_back(employee(120000));
+
+ int min_salary = 100000;
+ int u_limit = min_salary + 1;
+
+ bool BOOST_LOCAL_FUNCTION(const bind& min_salary, const bind& u_limit,
+ const employee& e) {
+ return e.salary >= min_salary && e.salary < u_limit;
+ } BOOST_LOCAL_FUNCTION_NAME(between)
+
+ // Pass local function to an STL algorithm as a template paramter (this
+ // cannot be done with plain member functions of local classes).
+ std::vector<employee>::iterator i = std::find_if(
+ employees.begin(), employees.end(), between);
+
+ BOOST_CHECK( i != employees.end() );
+ BOOST_CHECK( i->salary >= min_salary && i->salary < u_limit );
+}
+

Added: sandbox/closure/libs/local_function/example/scope_exit.cpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/scope_exit.cpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,109 @@
+
+// Copyright (C) 2009-2011 Lorenzo Caminiti
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0 (see accompanying file LICENSE_1_0.txt or a
+// copy at http://www.boost.org/LICENSE_1_0.txt).
+
+#include "scope_exit.hpp"
+#include <boost/foreach.hpp>
+#include <boost/typeof/typeof.hpp>
+#include <boost/typeof/std/vector.hpp>
+#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
+#define BOOST_TEST_MODULE TestScopeExit
+#include <boost/test/unit_test.hpp>
+#include <vector>
+#include <iostream>
+#include <sstream>
+
+class person; BOOST_TYPEOF_REGISTER_TYPE(person)
+class person {
+ friend class world;
+public:
+ typedef unsigned int id_t;
+ typedef unsigned int evolution_t;
+
+ person(void): id_(0), evolution_(0) {}
+
+ friend std::ostream& operator<<(std::ostream& o, person const& p) {
+ return o << "person(" << p.id_ << ", " << p.evolution_ << ")";
+ }
+private:
+ id_t id_;
+ evolution_t evolution_;
+};
+
+class world; BOOST_TYPEOF_REGISTER_TYPE(world)
+class world {
+public:
+ typedef unsigned int id_t;
+
+ world(void): next_id_(1) {}
+
+ void add_person(person const& a_person);
+
+ friend std::ostream& operator<<(std::ostream& o, world const& w) {
+ o << "world(" << w.next_id_ << ", {";
+ BOOST_FOREACH(person const& p, w.persons_) {
+ o << " " << p << ", ";
+ }
+ return o << "})";
+ }
+private:
+ id_t next_id_;
+ std::vector<person> persons_;
+};
+
+void world::add_person(person const& a_person) {
+ persons_.push_back(a_person);
+
+ // This block must be no-throw.
+ //[example_scope_exit
+ person& p = persons_.back();
+ person::evolution_t checkpoint = p.evolution_;
+
+ SCOPE_EXIT(const bind checkpoint, const bind& p, bind this_) {
+ if (checkpoint == p.evolution_) this_->persons_.pop_back();
+ } SCOPE_EXIT_END
+ //]
+
+ // ...
+
+ checkpoint = ++p.evolution_;
+
+ // Assign new id to the person.
+ world::id_t const prev_id = p.id_;
+ p.id_ = next_id_++;
+ SCOPE_EXIT(const bind checkpoint, const bind prev_id, bind& p,
+ bind& next_id_) {
+ if (checkpoint == p.evolution_) {
+ next_id_ = p.id_;
+ p.id_ = prev_id;
+ }
+ } SCOPE_EXIT_END
+
+ // ...
+
+ checkpoint = ++p.evolution_;
+}
+
+BOOST_AUTO_TEST_CASE( test_world_checkpoint ) {
+ person adam, eva;
+ std::ostringstream oss;
+ oss << adam;
+ std::cout << oss.str() << std::endl;
+ BOOST_CHECK( oss.str() == "person(0, 0)" );
+
+ oss.str("");
+ oss << eva;
+ std::cout << oss.str() << std::endl;
+ BOOST_CHECK( oss.str() == "person(0, 0)" );
+
+ world w;
+ w.add_person(adam);
+ w.add_person(eva);
+ oss.str("");
+ oss << w;
+ std::cout << oss.str() << std::endl;
+ BOOST_CHECK( oss.str() == "world(3, { person(1, 2), person(2, 2), })" );
+}
+

Added: sandbox/closure/libs/local_function/example/scope_exit.hpp
==============================================================================
--- (empty file)
+++ sandbox/closure/libs/local_function/example/scope_exit.hpp 2012-01-21 13:25:24 EST (Sat, 21 Jan 2012)
@@ -0,0 +1,41 @@
+
+#ifndef SCOPE_EXIT_HPP_
+#define SCOPE_EXIT_HPP_
+
+#include <boost/local_function.hpp>
+#include <boost/local_function/detail/preprocessor/line_counter.hpp>
+#include <boost/function.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/config.hpp>
+
+//[example_scope_exit_object
+struct scope_exit {
+ scope_exit(boost::function<void (void)> f): f_(f) {}
+ ~scope_exit(void) { f_(); }
+private:
+ boost::function<void (void)> f_;
+};
+//]
+
+// PRIVATE //
+
+#define SCOPE_EXIT_END_(id) \
+ BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(scope_exit_func_, id)) \
+ scope_exit BOOST_PP_CAT(scope_exit_, id)( \
+ BOOST_PP_CAT(scope_exit_func_, id));
+
+// PUBLIC //
+
+#ifdef BOOST_NO_VARIADIC_MACROS
+# define SCOPE_EXIT(void_or_seq) \
+ void BOOST_LOCAL_FUNCTION(void_or_seq)
+#else
+# define SCOPE_EXIT(...) \
+ void BOOST_LOCAL_FUNCTION(__VA_ARGS__)
+#endif
+
+#define SCOPE_EXIT_END \
+ SCOPE_EXIT_END_(BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER)
+
+#endif // #include guard
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk