forked from boostorg/preprocessor
Example on using BOOST_PP_WHILE()
[SVN r12611]
This commit is contained in:
91
example/linear_fib.c
Normal file
91
example/linear_fib.c
Normal file
@ -0,0 +1,91 @@
|
||||
/* Copyright (C) 2002
|
||||
* Housemarque Oy
|
||||
* http://www.housemarque.com
|
||||
*
|
||||
* Permission to copy, use, modify, sell and distribute this software is
|
||||
* granted provided this copyright notice appears in all copies. This
|
||||
* software is provided "as is" without express or implied warranty, and
|
||||
* with no claim as to its suitability for any purpose.
|
||||
*
|
||||
* See http://www.boost.org for most recent version.
|
||||
*/
|
||||
|
||||
/* This example shows how BOOST_PP_WHILE() can be used for implementing
|
||||
* macros.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/while.hpp>
|
||||
#include <boost/preprocessor/arithmetic/add.hpp>
|
||||
#include <boost/preprocessor/arithmetic/sub.hpp>
|
||||
#include <boost/preprocessor/list/adt.hpp>
|
||||
#include <boost/preprocessor/comparison/less_equal.hpp>
|
||||
#include <stdio.h>
|
||||
|
||||
/* First consider the following C implementation of Fibonacci. */
|
||||
|
||||
typedef struct linear_fib_state { int a0, a1, n; } linear_fib_state;
|
||||
|
||||
static int linear_fib_c( linear_fib_state p )
|
||||
{
|
||||
return p.n;
|
||||
}
|
||||
|
||||
static linear_fib_state linear_fib_f( linear_fib_state p )
|
||||
{
|
||||
linear_fib_state r = { p.a1, p.a0 + p.a1, p.n - 1 };
|
||||
return r;
|
||||
}
|
||||
|
||||
static int linear_fib( int n )
|
||||
{
|
||||
linear_fib_state p = { 0, 1, n };
|
||||
|
||||
while ( linear_fib_c(p) ) { p = linear_fib_f(p); }
|
||||
|
||||
return p.a0;
|
||||
}
|
||||
|
||||
/* Then consider the following preprocessor implementation of Fibonacci. */
|
||||
|
||||
#define LINEAR_FIB(N)\
|
||||
LINEAR_FIB_D(0,N)
|
||||
/* Since the macro is implemented using BOOST_PP_WHILE, the actual
|
||||
* implementation takes a depth as a parameter so that it can be called
|
||||
* inside a BOOST_PP_WHILE. The above easy-to-use version simply uses 0
|
||||
* as the depth and can not be called inside a BOOST_PP_WHILE.
|
||||
*/
|
||||
|
||||
#define LINEAR_FIB_D(D,N)\
|
||||
BOOST_PP_TUPLE_ELEM(3,0,BOOST_PP_WHILE##D(LINEAR_FIB_C,LINEAR_FIB_F,(0,1,N)))
|
||||
/* ^^^ ^^^ ^^ ^^ ^^^^^^^
|
||||
* #1 #2 #3 #3 #1
|
||||
*
|
||||
* #1) The state is a 3-tuple. After the iteration is finished, the first
|
||||
* element of the tuple is the result.
|
||||
*
|
||||
* #2) The WHILE primitive is "invoked" directly. BOOST_PP_WHILE(D,...)
|
||||
* can't be used because it would not be expanded by the C++ preprocessor.
|
||||
*
|
||||
* #3) ???_C is the condition and ???_F is the iteration macro.
|
||||
*/
|
||||
|
||||
#define LINEAR_FIB_C(D,P)\
|
||||
/* p.n */ BOOST_PP_TUPLE_ELEM(3,2,P)
|
||||
|
||||
#define LINEAR_FIB_F(D,P)\
|
||||
(/* p.a1 */ BOOST_PP_TUPLE_ELEM(3,1,P)\
|
||||
,/* p.a0+p.a1*/ BOOST_PP_ADD_D(D,BOOST_PP_TUPLE_ELEM(3,0,P),BOOST_PP_TUPLE_ELEM(3,1,P))\
|
||||
/* ^^ ^ \
|
||||
* BOOST_PP_ADD() uses BOOST_PP_WHILE(). Therefore we must\
|
||||
* pass the recursion depth explicitly to BOOST_PP_ADD_D().\
|
||||
*/\
|
||||
,/* p.n - 1 */ BOOST_PP_DEC(BOOST_PP_TUPLE_ELEM(3,2,P))\
|
||||
)
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("linear_fib(10) = %d\n", linear_fib(10));
|
||||
printf("LINEAR_FIB(10) = %d\n", LINEAR_FIB(10));
|
||||
|
||||
return 0;
|
||||
}
|
@ -16,7 +16,14 @@
|
||||
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
|
||||
/* Use of BOOST_PP_CAT() below allows macro expansion of __LINE__. */
|
||||
#define STATIC_ASSERT(EXPR)\
|
||||
typedef char BOOST_PP_CAT(static_assert_,__LINE__)[ (EXPR) ? 1 : -1 ]
|
||||
|
||||
STATIC_ASSERT(sizeof(int) <= sizeof(long));
|
||||
|
||||
/* This static assert is broken. The __LINE__ is not expanded as desired. */
|
||||
#define BROKEN_STATIC_ASSERT(EXPR)\
|
||||
typedef char static_assert_##__LINE__[ (EXPR) ? 1 : -1 ]
|
||||
|
||||
BROKEN_STATIC_ASSERT(sizeof(int) <= sizeof(long));
|
||||
|
Reference in New Issue
Block a user