|
Boost : |
Subject: Re: [boost] BOOST_PP array extension proposal
From: Gruenke,Matt (mgruenke_at_[hidden])
Date: 2015-09-14 00:46:50
-----Original Message-----
From: Boost [mailto:boost-bounces_at_[hidden]] On Behalf Of Edward Diener
Sent: Sunday, September 13, 2015 21:15
On 9/13/2015 12:29 PM, Gruenke,Matt wrote:
>> The reason I ask is that I've made a C equivalent of STL, using Boost PP.
>> BTW, is anyone aware of such a library already in existence?
> if by STL you mean the C++ standard template library I can not imagine
> how you could do that in straight C.
Of course, it's slightly more cumbersome to *use* than STL. You must pass in a bundle of type information to every operation, since the compiler won't do it for you. Constructor, destructor, copy constructor, etc. But it's just as powerful as STL, supporting generic algorithms that can operate on recursive containers of user-defined types. And the resulting composite types have unique C type signatures and can be passed into C functions (i.e. not just macros).
As this is rapidly getting off-topic, I'll just post a sample, before moving further discussion off the list. All of the following code compiles (in strict C89, IIRC) and works as advertised. If anyone is interested, I can probably post the nascent library up on github.
First, you must define a specific type. To make things easier to read, we bind names to each type signature:
#define mytype LIST( SEED( int ) ) /* list of ints */
#define loltype LIST( mytype ) /* list of lists of ints */
DEFINE( mytype )
DEFINE( loltype )
Now that the types are defined, you can make typedefs to refer to them more easily within your C code:
typedef TS_TYPENAME( mytype ) mytype_t;
typedef TS_TYPENAME( loltype ) loltype_t;
In fact, let's write some functions to print them:
void printitem( int val, const char **sep )
{
printf( "%s%d", *sep, val );
*sep = " ";
}
void printlist( mytype_t *l )
{
const char *empty = "";
const char **sep = ∅
FOR_EACH( mytype, *l, printitem, sep );
}
Let's also wrap the generic algorithm FIND() with some diagnostic code:
void find( mytype_t *l, int val )
{
ITER_TYPENAME( ITER( mytype ) ) i = END( mytype, *l );
FIND( mytype, *l, val, i );
printf( "%s %d\n", (i != END( mytype, *l ) ? "found" : "didn't find"), val );
}
Finally, instantiate the generic Bubble Sort. Since this expands into a function definition, there's one macro for declaring it (e.g. in a header file) and another for actually defining it (i.e. for use in just one of your .c files):
DECLARE_BUBBLESORT( loltype );
DEFINE_BUBBLESORT( loltype )
Let's create macros for referring to instances:
#define myvar_v VAR( mytype, myvar )
#define lolvar_v VAR( loltype, lolvar )
And now instantiate them:
INST_VAR( myvar_v );
INST_VAR( lolvar_v );
To initialize an instance, you call the generic INIT() macro. Likewise, CLEANUP() does what the name implies.
Now, a big, long main() function to test it out! Note the generic COPY() function, as well as alternate versions of INST(), INIT(), and CLEANUP() - one set takes a pair of type and instance names, while the other takes a VAR() expression.
int main()
{
# define yourvar_v VAR( mytype, yourvar )
INST( mytype, yourvar ); /* equivalent to INST_VAR( VAR( mytype, yourvar ) ) */
INST( loltype, lolcopy );
ITER_TYPENAME( ITER( loltype ) ) i_lol;
INIT_VAR( myvar_v );
INIT_VAR( lolvar_v );
printf( "size() %d\n", SIZE_VAR( myvar_v ) );
PUSH_BACK_VAR( myvar_v, 1 );
PUSH_BACK_VAR( myvar_v, 2 );
PUSH_BACK_VAR( myvar_v, 3 );
PUSH_BACK_VAR( lolvar_v, myvar );
PUSH_BACK_VAR( lolvar_v, myvar );
INIT_VAR( yourvar_v );
COPY( mytype, yourvar, myvar );
INIT( loltype, lolcopy );
COPY( loltype, lolcopy, lolvar );
printf( "size( mycopy ): %d\n", SIZE_VAR( yourvar_v ) );
printf( "size( lolcopy ): %d\n", SIZE( loltype, lolcopy ) );
printf( "front = %d back = %d\n", FRONT_VAR( yourvar_v ), BACK_VAR( yourvar_v ) );
find( &yourvar, 0 );
find( &VAR_INST( yourvar_v ), 1 );
find( &yourvar, 2 );
find( &yourvar, 17 );
PUSH_BACK_VAR( myvar_v, 4 );
printf( "Eq(): %d\n", EQ( mytype, myvar, yourvar ) );
printf( "Lt(): %d\n", LT( mytype, myvar, yourvar ) );
printf( "Gt(): %d\n", LT( mytype, yourvar, myvar ) );
PUSH_BACK( mytype, FRONT( loltype, lolcopy ), 4 );
printf( "Eq(): %d\n", EQ( loltype, lolvar, lolcopy ) );
printf( "Lt(): %d\n", LT( loltype, lolvar, lolcopy ) );
printf( "Gt(): %d\n", LT( loltype, lolcopy, lolvar ) );
i_lol = END( loltype, lolcopy );
FIND( loltype, lolcopy, myvar, i_lol );
if (i_lol != END( loltype, *lolcopy ))
{
printf( "found the list: " );
printlist( &DEREF( ITER( loltype ), i_lol ) );
printf( "\n" );
}
else printf( "didn't find the list.\n" );
printf( "FRONT( lolcopy ): " );
printlist( &FRONT( loltype, lolcopy ) );
printf( "\n" );
/* this is redundant, but it shows how to sort locally or via an instantiated version. */
BUBBLESORT( loltype, lolcopy );
CALL_BUBBLESORT( loltype, lolcopy );
printf( "FRONT( lolcopy ): " );
printlist( &FRONT( loltype, lolcopy ) );
printf( "\n" );
CLEANUP_VAR( myvar_v );
printf( "size(): %d\n", SIZE_VAR( myvar_v ) );
CLEANUP_VAR( yourvar_v );
printf( "size(): %d\n", SIZE_VAR( yourvar_v ) );
CLEANUP( loltype, lolvar );
printf( "size(): %d\n", SIZE_VAR( myvar_v ) );
CLEANUP( loltype, lolcopy );
printf( "size(): %d\n", SIZE_VAR( yourvar_v ) );
return 0;
}
Matt
________________________________
This e-mail contains privileged and confidential information intended for the use of the addressees named above. If you are not the intended recipient of this e-mail, you are hereby notified that you must not disseminate, copy or take any action in respect of any information contained in it. If you have received this e-mail in error, please notify the sender immediately by e-mail and immediately destroy this e-mail and its attachments.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk