[DEV] add v1.66.0

This commit is contained in:
2018-01-12 21:47:58 +01:00
parent 87059bb1af
commit a97e9ae7d4
49032 changed files with 7668950 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
# 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 ;
# Sun does not automatically detect type-of emulation mode (force it).
project : requirements <toolset>sun:<define>BOOST_TYPEOF_EMULATION ;
run add_cxx11_lambda.cpp ;
run add_global_functor.cpp ;
run add_local_functor.cpp ;
run add_phoenix.cpp ;
run const_block.cpp ;
compile-fail const_block_error.cpp : <variant>debug : ;
run const_block_error.cpp : <variant>release : ;
compile-fail const_block_error_cxx11_lambda.cpp ;
run expensive_copy_cxx11_lambda.cpp ;
run expensive_copy_local_function.cpp ;
run gcc_access.cpp ;
run gcc_lambda.cpp ;
run gcc_cxx11_lambda.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_cxx11_lambda_error.cpp ;
run noncopyable_local_function.cpp ;
run phoenix_factorial.cpp ;
run phoenix_factorial_local.cpp ;
# Only compile but do not run profiling programs (they take a long time to run).
exe profile_global_functor : profile_global_functor.cpp
: <library>/boost/chrono//boost_chrono
<library>/boost/system//boost_system
<link>static
;
exe profile_cxx11_lambda : profile_cxx11_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 ;

View File

@@ -0,0 +1,34 @@
// 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>
#ifdef BOOST_NO_CXX11_LAMBDAS
# error "lambda functions required"
#else
#include <boost/detail/lightweight_test.hpp>
#include <algorithm>
//[add_cxx11_lambda
int main(void) { // Some local scope.
int sum = 0, factor = 10; // Variables in scope to bind.
auto add = [factor, &sum](int num) { // C++11 only.
sum += factor * num;
};
add(1); // Call the lambda.
int nums[] = {2, 3};
std::for_each(nums, nums + 2, add); // Pass it to an algorithm.
BOOST_TEST(sum == 60); // Assert final summation value.
return boost::report_errors();
}
//]
#endif

View File

@@ -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/detail/lightweight_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.
};
int main(void) {
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_TEST(sum == 60);
return boost::report_errors();
}
//]

View File

@@ -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/detail/lightweight_test.hpp>
//[add_local_functor
int main(void) {
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_TEST(sum == 60);
return boost::report_errors();
}
//]

View File

@@ -0,0 +1,34 @@
// 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>
#include <boost/detail/lightweight_test.hpp>
#include <algorithm>
#include <iostream>
//[add_phoenix
int main(void) {
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, _1 // Access `sum` by reference.
]);
BOOST_TEST(sum == 60);
return boost::report_errors();
}
//]

View File

@@ -0,0 +1,25 @@
# 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
if len(sys.argv) < 2:
print "Usage: python " + sys.argv[0] + " COMMAND [COMMAND_OPTIONS]"
print "Measure run-time of executing the specified command."
exit(1)
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"

View File

@@ -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;
}

View File

@@ -0,0 +1,58 @@
// 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>
// PRIVATE //
#define CONST_BLOCK_BIND_(r, unused, i, var) \
BOOST_PP_COMMA_IF(i) const bind& var
//[const_block_macro
#define CONST_BLOCK_(variables) \
void BOOST_LOCAL_FUNCTION( \
BOOST_PP_IIF(BOOST_PP_LIST_IS_NIL(variables), \
void BOOST_PP_TUPLE_EAT(3) \
, \
BOOST_PP_LIST_FOR_EACH_I \
)(CONST_BLOCK_BIND_, ~, variables) \
)
//]
//[const_block_end_macro
#define CONST_BLOCK_END_(id) \
BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(const_block_, id)) \
BOOST_PP_CAT(const_block_, id)(); /* call local function immediately */
//]
// PUBLIC //
// Arguments `void | var1, var2, ... | (var1) (var2) ...`.
#ifdef BOOST_NO_CXX11_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

View File

@@ -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;
}

View File

@@ -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
#include <boost/config.hpp>
#ifdef BOOST_NO_CXX11_LAMBDAS
# error "requires lambda functions"
#else
#include <cassert>
int main(void) {
//[const_block_cxx11_lambda
int x = 1, y = 2;
const decltype(x)& const_x = x; // Constant so cannot be modified
const decltype(y)& const_y = y; // and reference so no copy.
[&const_x, &const_y]() { // Lambda functions (C++11 only).
assert(const_x = const_y); // Unfortunately, `const_` names.
}();
//]
return 0;
}
#endif // LAMBDAS

View File

@@ -0,0 +1,39 @@
// 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>
#ifdef BOOST_NO_CXX11_LAMBDAS
# error "lambda functions required"
#else
#include <iostream>
#include <cassert>
//[expensive_copy_cxx11_lambda
struct n {
int i;
n(int _i): i(_i) {}
n(n const& x): i(x.i) { // Some time consuming copy operation.
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;
}
//]
#endif // NO_LAMBDAS

View File

@@ -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/local_function.hpp>
#include <boost/typeof/typeof.hpp>
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
#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 operation.
for (unsigned i = 0; i < 10000; ++i) std::cout << '.';
}
};
BOOST_TYPEOF_REGISTER_TYPE(n) // Register for `bind& x` below.
int main(void) {
n x(-1);
void BOOST_LOCAL_FUNCTION(const bind& x) { // OK: No copy expensive
assert(x.i == -1); // copy but constant.
} BOOST_LOCAL_FUNCTION_NAME(f)
f();
return 0;
}
//]

View File

@@ -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>
#include <boost/detail/lightweight_test.hpp>
int main(void) {
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_TEST(access(nums, 1) == 1);
BOOST_TEST(access(nums, 2) == 2);
BOOST_TEST(access(nums, 3) == 3);
return boost::report_errors();
}

View File

@@ -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/config.hpp>
#ifdef BOOST_NO_CXX11_LAMBDAS
# error "lambda functions required"
#else
#include <boost/detail/lightweight_test.hpp>
#include <algorithm>
int main(void) {
//[gcc_cxx11_lambda
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_TEST(iter != end);
BOOST_TEST(*iter == val);
return boost::report_errors();
}
#endif // LAMBDAS

View File

@@ -0,0 +1,36 @@
// 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 __GNUC__
# error "GCC required (using non-standard GCC statement expressions)"
#else
#include "gcc_lambda.hpp"
#include <boost/detail/lightweight_test.hpp>
#include <algorithm>
int main(void) {
//[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_TEST(iter != end);
BOOST_TEST(*iter == val);
return boost::report_errors();
}
#endif // GCC

View File

@@ -0,0 +1,129 @@
// 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_CXX11_LAMBDAS
//[gcc_lambda_macro
# 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))
//[gcc_lambda_end_macro
#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_CXX11_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_CXX11_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

View File

@@ -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>
#include <boost/detail/lightweight_test.hpp>
int add_square(int a, int b) {
int BOOST_LOCAL_FUNCTION(int z) {
return z * z;
} BOOST_LOCAL_FUNCTION_NAME(square)
return square(a) + square(b);
}
int main(void) {
BOOST_TEST(add_square(2, 4) == 20);
return boost::report_errors();
}

View File

@@ -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>
#include <boost/detail/lightweight_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);
}
int main(void) {
int nums[] = {1, 2, 3};
hack(nums, 3);
BOOST_TEST(nums[0] == 1);
BOOST_TEST(nums[1] == 2);
BOOST_TEST(nums[2] == -1);
return boost::report_errors();
}

View File

@@ -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>
#include <boost/detail/lightweight_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 \
)))
int main(void) {
BOOST_TEST(IS_THIS_BACK(const bind this_) == 1);
BOOST_TEST(IS_THIS_BACK(const bind& x) == 0);
return boost::report_errors();
}
//]

View File

@@ -0,0 +1,71 @@
// 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
#include <boost/detail/lightweight_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_;
};
int main(void) {
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_TEST(sum == 200);
return boost::report_errors();
}
//]

View File

@@ -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
#include <boost/local_function.hpp>
#include <boost/typeof/typeof.hpp>
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
#include <boost/detail/lightweight_test.hpp>
#include <vector>
#include <algorithm>
struct v;
BOOST_TYPEOF_REGISTER_TYPE(v) // Register before `bind this_` below.
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);
}
};
int main(void) {
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_TEST(vn.nums.at(0) == -1);
BOOST_TEST(vn.nums.at(1) == 2);
BOOST_TEST(vn.nums.at(2) == -3);
return boost::report_errors();
}

View File

@@ -0,0 +1,44 @@
// 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/typeof/typeof.hpp>
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
#include <boost/detail/lightweight_test.hpp>
#include <vector>
#include <algorithm>
struct employee {
int salary;
explicit employee(const int& a_salary): salary(a_salary) {}
};
BOOST_TYPEOF_REGISTER_TYPE(employee) // Register for `NAME` below.
int main(void) {
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_TEST(i != employees.end());
BOOST_TEST(i->salary >= min_salary && i->salary < u_limit);
return boost::report_errors();
}

View File

@@ -0,0 +1,36 @@
// 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>
#ifdef BOOST_NO_CXX11_LAMBDAS
# error "lambda functions required"
#else
#include <boost/noncopyable.hpp>
#include <cassert>
//[noncopyable_cxx11_lambda_error
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;
}
//]
#endif // LAMBDAS

View File

@@ -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 <boost/noncopyable.hpp>
#include <boost/typeof/typeof.hpp>
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
#include <cassert>
//[noncopyable_local_function
struct n: boost::noncopyable {
int i;
n(int _i): i(_i) {}
};
BOOST_TYPEOF_REGISTER_TYPE(n) // Register for `bind& x` below.
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;
}
//]

View File

@@ -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>
#include <boost/detail/lightweight_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);
}
};
int main(void) {
using boost::phoenix::arg_names::arg1;
boost::phoenix::function<factorial_impl> factorial;
int i = 4;
BOOST_TEST(factorial(i)() == 24); // Call.
BOOST_TEST(factorial(arg1)(i) == 24); // Lazy call.
return boost::report_errors();
}
//]

View File

@@ -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>
#include <boost/detail/lightweight_test.hpp>
//[phoenix_factorial_local
int main(void) {
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_TEST(factorial(i)() == 24); // Call.
BOOST_TEST(factorial(arg1)(i) == 24); // Lazy call.
return boost::report_errors();
}
//]

Binary file not shown.

View File

@@ -0,0 +1,44 @@
// 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>
#ifdef BOOST_NO_CXX11_LAMBDAS
# error "lambda functions required"
#else
#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;
}
#endif // LAMBDAS

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -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;
}

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -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;
}

View File

@@ -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()
#include <boost/detail/lightweight_test.hpp>
#include <vector>
#include <iostream>
#include <sstream>
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_;
};
BOOST_TYPEOF_REGISTER_TYPE(person)
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_;
};
BOOST_TYPEOF_REGISTER_TYPE(world)
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_;
}
int main(void) {
person adam, eva;
std::ostringstream oss;
oss << adam;
std::cout << oss.str() << std::endl;
BOOST_TEST(oss.str() == "person(0, 0)");
oss.str("");
oss << eva;
std::cout << oss.str() << std::endl;
BOOST_TEST(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_TEST(oss.str() == "world(3, { person(1, 2), person(2, 2), })");
return boost::report_errors();
}

View File

@@ -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
#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 //
//[scope_exit_end_macro
#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_CXX11_VARIADIC_MACROS
# define SCOPE_EXIT(void_or_seq) \
void BOOST_LOCAL_FUNCTION(void_or_seq)
#else
//[scope_exit_macro
# 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