Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r77021 - trunk/libs/local_function/example
From: lorcaminiti_at_[hidden]
Date: 2012-02-14 19:35:58


Author: lcaminiti
Date: 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
New Revision: 77021
URL: http://svn.boost.org/trac/boost/changeset/77021

Log:
Added LocalFunction examples.
Added:
   trunk/libs/local_function/example/Jamfile.v2 (contents, props changed)
   trunk/libs/local_function/example/add_global_functor.cpp (contents, props changed)
   trunk/libs/local_function/example/add_local_functor.cpp (contents, props changed)
   trunk/libs/local_function/example/add_phoenix.cpp (contents, props changed)
   trunk/libs/local_function/example/chrono.py (contents, props changed)
   trunk/libs/local_function/example/const_block.cpp (contents, props changed)
   trunk/libs/local_function/example/const_block.hpp (contents, props changed)
   trunk/libs/local_function/example/const_block_err.cpp (contents, props changed)
   trunk/libs/local_function/example/expensive_copy_lambda.cpp (contents, props changed)
   trunk/libs/local_function/example/expensive_copy_local_function.cpp (contents, props changed)
   trunk/libs/local_function/example/gcc_access.cpp (contents, props changed)
   trunk/libs/local_function/example/gcc_lambda.cpp (contents, props changed)
   trunk/libs/local_function/example/gcc_lambda.hpp (contents, props changed)
   trunk/libs/local_function/example/gcc_lambda_cpp11.cpp (contents, props changed)
   trunk/libs/local_function/example/gcc_square.cpp (contents, props changed)
   trunk/libs/local_function/example/gcc_store.cpp (contents, props changed)
   trunk/libs/local_function/example/impl_pp_keyword.cpp (contents, props changed)
   trunk/libs/local_function/example/impl_tparam_tricks.cpp (contents, props changed)
   trunk/libs/local_function/example/n2529_this.cpp (contents, props changed)
   trunk/libs/local_function/example/n2550_find_if.cpp (contents, props changed)
   trunk/libs/local_function/example/noncopyable_lambda_err.cpp (contents, props changed)
   trunk/libs/local_function/example/noncopyable_local_function.cpp (contents, props changed)
   trunk/libs/local_function/example/phoenix_factorial.cpp (contents, props changed)
   trunk/libs/local_function/example/phoenix_factorial_local.cpp (contents, props changed)
   trunk/libs/local_function/example/profile.xls (contents, props changed)
   trunk/libs/local_function/example/profile_gcc_cpp11_debug.png (contents, props changed)
   trunk/libs/local_function/example/profile_gcc_cpp11_release.png (contents, props changed)
   trunk/libs/local_function/example/profile_gcc_debug.png (contents, props changed)
   trunk/libs/local_function/example/profile_gcc_release.png (contents, props changed)
   trunk/libs/local_function/example/profile_global_functor.cpp (contents, props changed)
   trunk/libs/local_function/example/profile_helpers.hpp (contents, props changed)
   trunk/libs/local_function/example/profile_lambda.cpp (contents, props changed)
   trunk/libs/local_function/example/profile_legend_global_functor.png (contents, props changed)
   trunk/libs/local_function/example/profile_legend_lambda.png (contents, props changed)
   trunk/libs/local_function/example/profile_legend_local_function.png (contents, props changed)
   trunk/libs/local_function/example/profile_legend_local_function_inline.png (contents, props changed)
   trunk/libs/local_function/example/profile_legend_local_functor.png (contents, props changed)
   trunk/libs/local_function/example/profile_legend_phoenix.png (contents, props changed)
   trunk/libs/local_function/example/profile_local_function.cpp (contents, props changed)
   trunk/libs/local_function/example/profile_local_function_inline.cpp (contents, props changed)
   trunk/libs/local_function/example/profile_local_functor.cpp (contents, props changed)
   trunk/libs/local_function/example/profile_msvc_debug.png (contents, props changed)
   trunk/libs/local_function/example/profile_msvc_release.png (contents, props changed)
   trunk/libs/local_function/example/profile_phoenix.cpp (contents, props changed)
   trunk/libs/local_function/example/scope_exit.cpp (contents, props changed)
   trunk/libs/local_function/example/scope_exit.hpp (contents, props changed)

Added: trunk/libs/local_function/example/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/Jamfile.v2 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,74 @@
+
+# Copyright (C) 2009-2012 Lorenzo Caminiti
+# Distributed under 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)
+# Home at http://www.boost.org/libs/local_function
+
+import testing ;
+
+project : requirements <library>/boost//unit_test_framework ;
+
+run add_global_functor.cpp ;
+run add_local_functor.cpp ;
+# I'm not sure why this does not compile... I've asked Booster.
+#run add_phoenix.cpp ;
+
+run const_block.cpp ;
+# Compilation fails for debug but not for release builds so commented out.
+#compile-fail const_block_err.cpp ;
+
+run expensive_copy_lambda.cpp ;
+run expensive_copy_local_function.cpp ;
+
+run gcc_access.cpp ;
+run gcc_lambda.cpp ;
+run gcc_lambda_cpp11.cpp ;
+run gcc_square.cpp ;
+run gcc_store.cpp ;
+
+run impl_pp_keyword.cpp ;
+run impl_tparam_tricks.cpp ;
+
+run n2529_this.cpp ;
+run n2550_find_if.cpp ;
+
+compile-fail noncopyable_lambda_err.cpp ;
+run noncopyable_local_function.cpp ;
+
+run phoenix_factorial.cpp ;
+run phoenix_factorial_local.cpp ;
+
+exe profile_global_functor : profile_global_functor.cpp
+ : <library>/boost/chrono//boost_chrono
+ <library>/boost/system//boost_system
+ <link>static
+ ;
+exe profile_lambda : profile_lambda.cpp
+ : <library>/boost/chrono//boost_chrono
+ <library>/boost/system//boost_system
+ <link>static
+ ;
+exe profile_local_function : profile_local_function.cpp
+ : <library>/boost/chrono//boost_chrono
+ <library>/boost/system//boost_system
+ <link>static
+ ;
+exe profile_local_function_inline : profile_local_function_inline.cpp
+ : <library>/boost/chrono//boost_chrono
+ <library>/boost/system//boost_system
+ <link>static
+ ;
+exe profile_local_functor : profile_local_functor.cpp
+ : <library>/boost/chrono//boost_chrono
+ <library>/boost/system//boost_system
+ <link>static
+ ;
+exe profile_phoenix : profile_phoenix.cpp
+ : <library>/boost/chrono//boost_chrono
+ <library>/boost/system//boost_system
+ <link>static
+ ;
+
+run scope_exit.cpp ;
+

Added: trunk/libs/local_function/example/add_global_functor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/add_global_functor.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,37 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#define BOOST_TEST_MODULE TestAddGlobalFunctor
+#include <boost/test/unit_test.hpp>
+#include <algorithm>
+
+//[add_global_functor
+// Unfortunately, cannot be defined locally (so not a real alternative).
+struct global_add { // Unfortunately, boilerplate code to program the class.
+ global_add(int& _sum, int _factor): sum(_sum), factor(_factor) {}
+
+ inline void operator()(int num) { // Body uses C++ statement syntax.
+ sum += factor * num;
+ }
+private: // Unfortunately, cannot bind so repeat variable types.
+ int& sum; // Access `sum` by reference.
+ const int factor; // Make `factor` constant.
+};
+
+BOOST_AUTO_TEST_CASE( test_add_global_functor ) {
+ int sum = 0, factor = 10;
+
+ global_add add(sum, factor);
+
+ add(1);
+ int nums[] = {2, 3};
+ std::for_each(nums, nums + 2, add); // Passed as template parameter.
+
+ BOOST_CHECK( sum == 60 );
+}
+//]
+

Added: trunk/libs/local_function/example/add_local_functor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/add_local_functor.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,35 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#define BOOST_TEST_MODULE TestAddLocalFunctor
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( test_add_local_functor )
+//[add_local_functor
+{
+ int sum = 0, factor = 10;
+
+ struct local_add { // Unfortunately, boilerplate code to program the class.
+ local_add(int& _sum, int _factor): sum(_sum), factor(_factor) {}
+
+ inline void operator()(int num) { // Body uses C++ statement syntax.
+ sum += factor * num;
+ }
+ private: // Unfortunately, cannot bind so repeat variable types.
+ int& sum; // Access `sum` by reference.
+ const int factor; // Make `factor` constant.
+ } add(sum, factor);
+
+ add(1);
+ int nums[] = {2, 3};
+ // Unfortunately, cannot pass as template parameter to `std::for_each`.
+ for(size_t i = 0; i < 2; ++i) add(nums[i]);
+
+ BOOST_CHECK( sum == 60 );
+}
+//]
+

Added: trunk/libs/local_function/example/add_phoenix.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/add_phoenix.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,35 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/spirit/include/phoenix.hpp>
+#define BOOST_TEST_MODULE TestAddPhoenix
+#include <boost/test/unit_test.hpp>
+#include <algorithm>
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE( test_add_phoenix )
+//[add_phoenix
+{
+ using boost::phoenix::let;
+ using boost::phoenix::local_names::_f;
+ using boost::phoenix::cref;
+ using boost::phoenix::ref;
+ using boost::phoenix::arg_names::_1;
+
+ int sum = 0, factor = 10;
+ int nums[] = {1, 2, 3};
+
+ // Passed to template, `factor` by constant, and defined in expression.
+ std::for_each(nums, nums + 3, let(_f = cref(factor))[
+ // Unfortunately, body cannot use C++ statement syntax.
+ ref(sum) += _f * _1 // Access `sum` by reference.
+ ]);
+
+ BOOST_CHECK( sum == 60 );
+}
+//]
+

Added: trunk/libs/local_function/example/chrono.py
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/chrono.py 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,22 @@
+
+# Copyright (C) 2009-2012 Lorenzo Caminiti
+# Distributed under 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)
+# Home at http://www.boost.org/libs/local_function
+
+import sys
+import time
+import os
+
+# Usage: python crono.py COMMAND [COMMAND_OPTIONS]
+
+cmd = ""
+for arg in sys.argv[1:]: cmd += str(arg) + " "
+
+start = time.time()
+ret = os.system(cmd)
+sec = time.time() - start
+
+if (ret == 0): print "\n" + str(sec) + "s"
+

Added: trunk/libs/local_function/example/const_block.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/const_block.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,18 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#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: trunk/libs/local_function/example/const_block.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/const_block.hpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,55 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#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: trunk/libs/local_function/example/const_block_err.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/const_block_err.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,20 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include "const_block.hpp"
+#include <cassert>
+
+int main(void) {
+ //[const_block
+ int x = 1, y = 2;
+ CONST_BLOCK(x, y) { // Constant block.
+ assert(x = y); // Compiler error.
+ } CONST_BLOCK_END
+ //]
+ return 0;
+}
+

Added: trunk/libs/local_function/example/expensive_copy_lambda.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/expensive_copy_lambda.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,40 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_LAMBDAS
+
+#include <iostream>
+#include <cassert>
+
+//[expensive_copy_lambda
+struct n {
+ int i;
+ n(int _i): i(_i) {}
+ n(n const& x): i(x.i) { // Some time consuming copy.
+ for (unsigned i = 0; i < 10000; ++i) std::cout << '.';
+ }
+};
+
+int main(void) {
+ n x(-1);
+
+ auto f = [x]() { // Problem: Expensive copy, but if bind
+ assert( x.i == -1); // by `&x` then `x` is not constant.
+ };
+ f();
+
+ return 0;
+}
+//]
+
+#else // NO_LAMBDAS
+
+int main(void) { return 0; } // Trivial program.
+
+#endif // NO_LAMBDAS
+

Added: trunk/libs/local_function/example/expensive_copy_local_function.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/expensive_copy_local_function.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,32 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#include <iostream>
+#include <cassert>
+
+//[expensive_copy_local_function
+struct n {
+ int i;
+ n(int _i): i(_i) {}
+ n(n const& x): i(x.i) { // Some time consuming copy.
+ for (unsigned i = 0; i < 10000; ++i) std::cout << '.';
+ }
+};
+
+int main(void) {
+ n x(-1);
+
+ void BOOST_LOCAL_FUNCTION(const bind& x) { // OK: No copy
+ assert( x.i == -1 ); // and constant.
+ } BOOST_LOCAL_FUNCTION_NAME(f)
+ f();
+
+ return 0;
+}
+//]
+

Added: trunk/libs/local_function/example/gcc_access.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/gcc_access.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,23 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#define BOOST_TEST_MODULE TestGccAccess
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( test_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: trunk/libs/local_function/example/gcc_lambda.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/gcc_lambda.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,38 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/config.hpp>
+#if defined(__GCC__) || !defined(BOOST_NO_LAMBDAS)
+
+#include "gcc_lambda.hpp"
+#define BOOST_TEST_MODULE TestGccLambda
+#include <boost/test/unit_test.hpp>
+#include <algorithm>
+
+BOOST_AUTO_TEST_CASE( test_gcc_lambda ) {
+ //[gcc_lambda
+ int val = 2;
+ int nums[] = {1, 2, 3};
+ int* end = nums + 3;
+
+ int* iter = std::find_if(nums, end,
+ GCC_LAMBDA(const bind val, int num, return bool) {
+ return num == val;
+ } GCC_LAMBDA_END
+ );
+ //]
+
+ BOOST_CHECK( iter != end );
+ BOOST_CHECK( *iter == val );
+}
+
+#else // GCC || !NO_LAMBDAS
+
+int main(void) { return 0; }
+
+#endif // GCC || !NO_LAMBDAS
+

Added: trunk/libs/local_function/example/gcc_lambda.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/gcc_lambda.hpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,125 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#ifndef GCC_LAMBDA_HPP_
+#define GCC_LAMBDA_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/local_function/detail/preprocessor/keyword/return.hpp>
+#include <boost/local_function/detail/preprocessor/keyword/const_bind.hpp>
+#include <boost/local_function/detail/preprocessor/keyword/bind.hpp>
+#include <boost/preprocessor/list/for_each_i.hpp>
+#include <boost/preprocessor/list/fold_left.hpp>
+#include <boost/preprocessor/list/append.hpp>
+#include <boost/preprocessor/list/enum.hpp>
+#include <boost/preprocessor/list/adt.hpp>
+#include <boost/preprocessor/tuple/elem.hpp>
+#include <boost/preprocessor/tuple/eat.hpp>
+#include <boost/preprocessor/control/iif.hpp>
+#include <boost/preprocessor/punctuation/comma_if.hpp>
+#include <boost/preprocessor/facilities/expand.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/config.hpp>
+
+// PRIVATE //
+
+#define GCC_LAMBDA_SPLIT_BIND_(elem, binds, params, results) \
+ (BOOST_PP_LIST_APPEND(binds, (elem, BOOST_PP_NIL)), params, results)
+
+#define GCC_LAMBDA_SPLIT_PARAM_(elem, binds, params, results) \
+ (binds, BOOST_PP_LIST_APPEND(params, (elem, BOOST_PP_NIL)), results)
+
+#define GCC_LAMBDA_SPLIT_RESULT_(elem, binds, params, results) \
+ (binds, params, BOOST_PP_LIST_APPEND(results, (elem, BOOT_PP_NIL)))
+
+#define GCC_LAMBDA_SPLIT_DISPATCH_(d, binds_params_results, elem) \
+ BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_RETURN_FRONT(elem), \
+ GCC_LAMBDA_SPLIT_RESULT_ \
+ , BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_BIND_FRONT(elem), \
+ GCC_LAMBDA_SPLIT_BIND_ \
+ , BOOST_PP_IIF(BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_IS_CONST_BIND_FRONT( \
+ elem), \
+ GCC_LAMBDA_SPLIT_BIND_ \
+ , /* no result, no bind, and no const bind so it's param */ \
+ GCC_LAMBDA_SPLIT_PARAM_ \
+ )))(elem, BOOST_PP_TUPLE_ELEM(3, 0, binds_params_results), \
+ BOOST_PP_TUPLE_ELEM(3, 1, binds_params_results), \
+ BOOST_PP_TUPLE_ELEM(3, 2, binds_params_results))
+
+#define GCC_LAMBDA_SPLIT_(list) \
+ BOOST_PP_LIST_FOLD_LEFT(GCC_LAMBDA_SPLIT_DISPATCH_, \
+ (BOOST_PP_NIL, BOOST_PP_NIL, BOOST_PP_NIL), list)
+
+#define GCC_LAMBDA_REMOVE_CONST_BIND_(r, unused, i, elem) \
+ BOOST_PP_COMMA_IF(i) \
+ BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_CONST_BIND_REMOVE_FRONT(elem)
+
+#define GCC_LAMBDA_RESULT_TYPE_(results) \
+ BOOST_LOCAL_FUNCTION_DETAIL_PP_KEYWORD_RETURN_REMOVE_FRONT( \
+ BOOST_PP_LIST_FIRST(results))
+
+#ifdef BOOST_NO_LAMBDAS
+# define GCC_LAMBDA_(binds, params, results) \
+ ({ /* open statement expression (GCC extension only) */ \
+ BOOST_LOCAL_FUNCTION( \
+ BOOST_PP_LIST_ENUM(BOOST_PP_LIST_APPEND(binds, \
+ BOOST_PP_LIST_APPEND(params, \
+ BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(results), \
+ (return void, BOOST_PP_NIL) /* default for lambdas */ \
+ , \
+ results \
+ )\
+ ) \
+ )) \
+ )
+#else
+# define GCC_LAMBDA_(binds, params, results) \
+ /* ignore const binding because not supported by C++11 lambdas */ \
+ [ BOOST_PP_LIST_FOR_EACH_I(GCC_LAMBDA_REMOVE_CONST_BIND_, ~, binds) ] \
+ ( BOOST_PP_LIST_ENUM(params) ) \
+ BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(results), \
+ BOOST_PP_TUPLE_EAT(1) /* void result type (default) */ \
+ , \
+ -> GCC_LAMBDA_RESULT_TYPE_ \
+ )(results)
+#endif
+
+#define GCC_LAMBDA_TUPLE_(binds_params_results) \
+ GCC_LAMBDA_(BOOST_PP_TUPLE_ELEM(3, 0, binds_params_results), \
+ BOOST_PP_TUPLE_ELEM(3, 1, binds_params_results), \
+ BOOST_PP_TUPLE_ELEM(3, 2, binds_params_results))
+
+#define GCC_LAMBDA_END_(id) \
+ BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(gcc_lambda_, id)) \
+ BOOST_PP_CAT(gcc_lambda_, id); \
+ }) /* close statement expression (GCC extension only) */
+
+// PUBLIC //
+
+// Same arguments as for local functions but respect to C++11 lambdas:
+// const bind v is =v, bind& v is &v, void if no return specified, no = or &.
+#ifdef BOOST_NO_VARIADIC_MACROS
+# define GCC_LAMBDA(void_or_seq) \
+ GCC_LAMBDA_TUPLE_(GCC_LAMBDA_SPLIT_( \
+ BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(void_or_seq)))
+#else
+# define GCC_LAMBDA(...) \
+ GCC_LAMBDA_TUPLE_(GCC_LAMBDA_SPLIT_( \
+ BOOST_LOCAL_FUNCTION_DETAIL_PP_VOID_LIST(__VA_ARGS__)))
+#endif
+
+#ifdef BOOST_NO_LAMBDAS
+# define GCC_LAMBDA_END \
+ GCC_LAMBDA_END_(BOOST_LOCAL_FUNCTION_DETAIL_PP_LINE_COUNTER)
+#else
+# define GCC_LAMBDA_END /* nothing */
+#endif
+
+#endif // #include guard
+

Added: trunk/libs/local_function/example/gcc_lambda_cpp11.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/gcc_lambda_cpp11.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,37 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_LAMBDAS
+
+#define BOOST_TEST_MODULE TestGccLambdaCpp11
+#include <boost/test/unit_test.hpp>
+#include <algorithm>
+
+BOOST_AUTO_TEST_CASE( test_gcc_lambda_cpp11 ) {
+ //[gcc_lambda_cpp11
+ int val = 2;
+ int nums[] = {1, 2, 3};
+ int* end = nums + 3;
+
+ int* iter = std::find_if(nums, end,
+ [val](int num) -> bool {
+ return num == val;
+ }
+ );
+ //]
+
+ BOOST_CHECK( iter != end );
+ BOOST_CHECK( *iter == val );
+}
+
+#else // NO_LAMBDAS
+
+int main(void) { return 0; } // Trivial test.
+
+#endif // NO_LAMBDAS
+

Added: trunk/libs/local_function/example/gcc_square.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/gcc_square.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,23 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#define BOOST_TEST_MODULE TestGccSquare
+#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( test_gcc_square ) {
+ BOOST_CHECK( add_square(2.0, 4.0) == 20.0 );
+}
+

Added: trunk/libs/local_function/example/gcc_store.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/gcc_store.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,33 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#include <boost/function.hpp>
+#define BOOST_TEST_MODULE TestGccStore
+#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( test_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: trunk/libs/local_function/example/impl_pp_keyword.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/impl_pp_keyword.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,28 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+//[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 TestImplPpKeyword
+#include <boost/test/unit_test.hpp>
+
+// Expand to 1 if space-separated tokens end with `this_`, 0 otherwise.
+#define IS_THIS_BACK(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( test_impl_pp_keyword ) {
+ BOOST_CHECK( IS_THIS_BACK(const bind this_) == 1 );
+ BOOST_CHECK( IS_THIS_BACK(const bind& x) == 0 );
+}
+//]
+

Added: trunk/libs/local_function/example/impl_tparam_tricks.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/impl_tparam_tricks.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,72 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+//[impl_tparam_tricks
+#define BOOST_TEST_MODULE TestImplTparamTricks
+#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( test_impl_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: trunk/libs/local_function/example/n2529_this.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/n2529_this.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,42 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#define BOOST_TEST_MODULE TestN2529This
+#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( test_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: trunk/libs/local_function/example/n2550_find_if.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/n2550_find_if.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,41 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#define BOOST_TEST_MODULE TestN2550FindIf
+#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( test_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: trunk/libs/local_function/example/noncopyable_lambda_err.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/noncopyable_lambda_err.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,37 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_LAMBDAS
+
+#include <boost/noncopyable.hpp>
+#include <cassert>
+
+//[noncopyable_lambda_err
+struct n: boost::noncopyable {
+ int i;
+ n(int _i): i(_i) {}
+};
+
+int main(void) {
+ n x(-1);
+
+ auto f = [x](void) { // Error: x is non-copyable, but if
+ assert( x.i == -1 ); // bind `&x` then `x` is not constant.
+ };
+ f();
+
+ return 0;
+}
+//]
+
+#else // NO_LAMBDAS
+
+#error "Trivial failure."
+
+#endif // NO_LAMBDAS
+

Added: trunk/libs/local_function/example/noncopyable_local_function.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/noncopyable_local_function.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,29 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#include <boost/noncopyable.hpp>
+#include <cassert>
+
+//[noncopyable_local_function
+struct n: boost::noncopyable {
+ int i;
+ n(int _i): i(_i) {}
+};
+
+int main() {
+ n x(-1);
+
+ void BOOST_LOCAL_FUNCTION(const bind& x) { // OK: No copy
+ assert( x.i == -1 ); // and constant.
+ } BOOST_LOCAL_FUNCTION_NAME(f)
+ f();
+
+ return 0;
+}
+//]
+

Added: trunk/libs/local_function/example/phoenix_factorial.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/phoenix_factorial.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,40 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/phoenix/core.hpp>
+#include <boost/phoenix/function.hpp>
+#define BOOST_TEST_MODULE TestPhoenixFactorial
+#include <boost/test/unit_test.hpp>
+
+//[phoenix_factorial
+struct factorial_impl { // Phoenix function from global functor.
+ template<typename Sig>
+ struct result;
+
+ template<typename This, typename Arg>
+ struct result<This (Arg)> : result<This (Arg const&)> {};
+
+ template<typename This, typename Arg>
+ struct result<This (Arg&)> { typedef Arg type; };
+
+ template<typename Arg> // Polymorphic.
+ Arg operator()(Arg n) const {
+ return (n <= 0) ? 1 : n * (*this)(n - 1);
+ }
+};
+
+BOOST_AUTO_TEST_CASE( test_phoenix_factorial ) {
+ using boost::phoenix::arg_names::arg1;
+
+ boost::phoenix::function<factorial_impl> factorial;
+
+ int i = 4;
+ BOOST_CHECK( factorial(i)() == 24 ); // Call.
+ BOOST_CHECK( factorial(arg1)(i) == 24 ); // Lazy call.
+}
+//]
+

Added: trunk/libs/local_function/example/phoenix_factorial_local.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/phoenix_factorial_local.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,31 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#include <boost/function.hpp>
+#include <boost/phoenix/core.hpp>
+#include <boost/phoenix/function.hpp>
+#define BOOST_TEST_MODULE TestPhoenixFactorialLocal
+#include <boost/test/unit_test.hpp>
+
+//[phoenix_factorial_local
+BOOST_AUTO_TEST_CASE( test_phoenix_factorial_local ) {
+ using boost::phoenix::arg_names::arg1;
+
+ int BOOST_LOCAL_FUNCTION(int n) { // Unfortunately, monomorphic.
+ return (n <= 0) ? 1 : n * factorial_impl(n - 1);
+ } BOOST_LOCAL_FUNCTION_NAME(recursive factorial_impl)
+
+ boost::phoenix::function< boost::function<int (int)> >
+ factorial(factorial_impl); // Phoenix function from local function.
+
+ int i = 4;
+ BOOST_CHECK( factorial(i)() == 24 ); // Call.
+ BOOST_CHECK( factorial(arg1)(i) == 24 ); // Lazy call.
+}
+//]
+

Added: trunk/libs/local_function/example/profile.xls
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_gcc_cpp11_debug.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_gcc_cpp11_release.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_gcc_debug.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_gcc_release.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_global_functor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/profile_global_functor.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,51 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/chrono.hpp>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include "profile_helpers.hpp"
+
+struct global_add {
+ global_add(double& _sum, const int& _factor): sum(_sum), factor(_factor) {}
+ inline void operator()(const double& num) {
+ sum += factor * num;
+ }
+private:
+ double& sum;
+ const int& factor;
+};
+
+int main(int argc, char* argv[]) {
+ unsigned long size = 0, trials =0;
+ profile::args(argc, argv, size, trials);
+
+ double sum = 0.0;
+ int factor = 1;
+
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+ global_add add(sum, factor);
+ boost::chrono::duration<double> decl_sec =
+ boost::chrono::system_clock::now() - start;
+
+ std::vector<double> v(size);
+ std::fill(v.begin(), v.end(), 1.0);
+
+ boost::chrono::duration<double> trials_sec;
+ for(unsigned long i = 0; i < trials; ++i) {
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+ std::for_each(v.begin(), v.end(), add);
+ trials_sec += boost::chrono::system_clock::now() - start;
+ }
+
+ profile::display(size, trials, sum, trials_sec.count(), decl_sec.count());
+ return 0;
+}
+

Added: trunk/libs/local_function/example/profile_helpers.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/profile_helpers.hpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,54 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#ifndef PROFILE_HELPERS_HPP_
+#define PROFILE_HELPERS_HPP_
+
+#include <iostream>
+#include <cassert>
+
+namespace profile {
+
+void args(int argc, char* argv[], unsigned long& size, unsigned long& trials) {
+ size = 100000000; // Defaults.
+ trials = 10; // Default.
+ if (argc != 1 && argc != 2 && argc != 3) {
+ std::cerr << "ERROR: Incorrect argument(s)" << std::endl;
+ std::cerr << "Usage: " << argv[0] << " [SIZE] [TRIALS]" <<
+ std::endl;
+ std::cerr << "Defaults: SIZE = " << double(size) << ", TRIALS = " <<
+ double(trials) << std::endl;
+ exit(1);
+ }
+ if (argc >= 2) size = atol(argv[1]);
+ if (argc >= 3) trials = atol(argv[2]);
+
+ std::clog << "vector size = " << double(size) << std::endl;
+ std::clog << "number of trials = " << double(trials) << std::endl;
+ std::clog << "number of calls = " << double(size) * double(trials) <<
+ std::endl;
+}
+
+void display(const unsigned long& size, const unsigned long& trials,
+ const double& sum, const double& trials_sec,
+ const double& decl_sec = 0.0) {
+ std::clog << "sum = " << sum << std::endl;
+ std::clog << "declaration run-time [s] = " << decl_sec << std::endl;
+ std::clog << "trials run-time [s] = " << trials_sec << std::endl;
+
+ double avg_sec = decl_sec + trials_sec / trials;
+ std::clog << "average run-time [s] = declaration run-time + trials " <<
+ "run-time / number of trials = " << std::endl;
+ std::cout << avg_sec << std::endl; // To cout so it can be parsed easily.
+
+ assert(sum == double(size) * double(trials));
+}
+
+} // namespace
+
+#endif // #include guard
+

Added: trunk/libs/local_function/example/profile_lambda.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/profile_lambda.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,46 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_LAMBDAS
+
+#include <boost/chrono.hpp>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include "profile_helpers.hpp"
+
+int main(int argc, char* argv[]) {
+ unsigned long size = 0, trials = 0;
+ profile::args(argc, argv, size, trials);
+
+ double sum = 0.0;
+ int factor = 1;
+
+ std::vector<double> v(size);
+ std::fill(v.begin(), v.end(), 1.0);
+
+ boost::chrono::duration<double> trials_sec;
+ for(unsigned long i = 0; i < trials; ++i) {
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+ std::for_each(v.begin(), v.end(), [&sum, factor](const double& num) {
+ sum += factor * num;
+ });
+ trials_sec += boost::chrono::system_clock::now() - start;
+ }
+
+ profile::display(size, trials, sum, trials_sec.count());
+ return 0;
+}
+
+#else // NO_LAMBDAS
+
+int main(void) { return 0; } // Trivial program.
+
+#endif // NO_LAMBDAS
+

Added: trunk/libs/local_function/example/profile_legend_global_functor.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_legend_lambda.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_legend_local_function.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_legend_local_function_inline.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_legend_local_functor.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_legend_phoenix.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_local_function.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/profile_local_function.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,45 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#include <boost/chrono.hpp>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include "profile_helpers.hpp"
+
+int main(int argc, char* argv[]) {
+ unsigned long size = 0, trials = 0;
+ profile::args(argc, argv, size, trials);
+
+ double sum = 0.0;
+ int factor = 1;
+
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+ void BOOST_LOCAL_FUNCTION(
+ const double& num, bind& sum, const bind& factor) {
+ sum += factor * num;
+ } BOOST_LOCAL_FUNCTION_NAME(add)
+ boost::chrono::duration<double> decl_sec =
+ boost::chrono::system_clock::now() - start;
+
+ std::vector<double> v(size);
+ std::fill(v.begin(), v.end(), 1.0);
+
+ boost::chrono::duration<double> trials_sec;
+ for(unsigned long i = 0; i < trials; ++i) {
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+ std::for_each(v.begin(), v.end(), add);
+ trials_sec += boost::chrono::system_clock::now() - start;
+ }
+
+ profile::display(size, trials, sum, trials_sec.count(), decl_sec.count());
+ return 0;
+}
+

Added: trunk/libs/local_function/example/profile_local_function_inline.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/profile_local_function_inline.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,45 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/local_function.hpp>
+#include <boost/chrono.hpp>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include "profile_helpers.hpp"
+
+int main(int argc, char* argv[]) {
+ unsigned long size = 0, trials = 0;
+ profile::args(argc, argv, size, trials);
+
+ double sum = 0.0;
+ int factor = 1;
+
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+ void BOOST_LOCAL_FUNCTION(
+ const double& num, bind& sum, const bind& factor) {
+ sum += factor * num;
+ } BOOST_LOCAL_FUNCTION_NAME(inline add) // Inlined.
+ boost::chrono::duration<double> decl_sec =
+ boost::chrono::system_clock::now() - start;
+
+ std::vector<double> v(size);
+ std::fill(v.begin(), v.end(), 1.0);
+
+ boost::chrono::duration<double> trials_sec;
+ for(unsigned long i = 0; i < trials; ++i) {
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+ for(unsigned long j = 0; j < v.size(); ++j) add(v[j]); // No for_each.
+ trials_sec += boost::chrono::system_clock::now() - start;
+ }
+
+ profile::display(size, trials, sum, trials_sec.count(), decl_sec.count());
+ return 0;
+}
+

Added: trunk/libs/local_function/example/profile_local_functor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/profile_local_functor.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,50 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/chrono.hpp>
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include "profile_helpers.hpp"
+
+int main(int argc, char* argv[]) {
+ unsigned long size = 0, trials = 0;
+ profile::args(argc, argv, size, trials);
+
+ double sum = 0.0;
+ int factor = 1;
+
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+ struct local_add {
+ local_add(double& _sum, const int& _factor):
+ sum(_sum), factor(_factor) {}
+ inline void operator()(const double& num) {
+ sum += factor * num;
+ }
+ private:
+ double& sum;
+ const int& factor;
+ } add(sum, factor);
+ boost::chrono::duration<double> decl_sec =
+ boost::chrono::system_clock::now() - start;
+
+ std::vector<double> v(size);
+ std::fill(v.begin(), v.end(), 1.0);
+
+ boost::chrono::duration<double> trials_sec;
+ for(unsigned long i = 0; i < trials; ++i) {
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+ for(unsigned long j = 0; j < v.size(); ++j) add(v[j]); // No for_each.
+ trials_sec += boost::chrono::system_clock::now() - start;
+ }
+
+ profile::display(size, trials, sum, trials_sec.count(), decl_sec.count());
+ return 0;
+}
+

Added: trunk/libs/local_function/example/profile_msvc_debug.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_msvc_release.png
==============================================================================
Binary file. No diff available.

Added: trunk/libs/local_function/example/profile_phoenix.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/profile_phoenix.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,45 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#include <boost/spirit/home/phoenix/statement/sequence.hpp>
+#include <boost/spirit/home/phoenix/core/reference.hpp>
+#include <boost/spirit/home/phoenix/core/argument.hpp>
+#include <boost/spirit/home/phoenix/operator/arithmetic.hpp>
+#include <boost/chrono.hpp>
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include "profile_helpers.hpp"
+
+int main(int argc, char* argv[]) {
+ unsigned long size = 0, trials = 0;
+ profile::args(argc, argv, size, trials);
+
+ double sum = 0.0;
+ int factor = 1;
+
+ std::vector<double> v(size);
+ std::fill(v.begin(), v.end(), 1.0);
+
+ boost::chrono::duration<double> trials_sec;
+ for(unsigned long i = 0; i < trials; ++i) {
+ boost::chrono::system_clock::time_point start =
+ boost::chrono::system_clock::now();
+
+ using boost::phoenix::ref;
+ using boost::phoenix::arg_names::_1;
+ std::for_each(v.begin(), v.end(), (
+ ref(sum) += factor * _1
+ ));
+
+ trials_sec += boost::chrono::system_clock::now() - start;
+ }
+
+ profile::display(size, trials, sum, trials_sec.count());
+ return 0;
+}
+

Added: trunk/libs/local_function/example/scope_exit.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/scope_exit.cpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,110 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#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.
+ //[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_scope_exit ) {
+ 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: trunk/libs/local_function/example/scope_exit.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/local_function/example/scope_exit.hpp 2012-02-14 19:35:55 EST (Tue, 14 Feb 2012)
@@ -0,0 +1,47 @@
+
+// Copyright (C) 2009-2012 Lorenzo Caminiti
+// Distributed under 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)
+// Home at http://www.boost.org/libs/local_function
+
+#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>
+
+//[scope_exit_class
+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