CCL vs STL: a comparison


J

jacob navia

Here is a comparison of two source codes that use the C++ STL and the
C containers library (ccl).

First, the C++ example:

// Standard Template Library example

#include <iostream>
#include <list>
using namespace std;

// Simple example uses type int

int main(void)
{
list<int> L;
L.push_back(0); // Insert a new element at the end
L.push_front(0); // Insert a new element at the beginning
L.insert(++L.begin(),2);// Insert "2" before position of first argument
// (Place before second argument)
L.push_back(5);
L.push_back(6);

list<int>::iterator i;

for(i=L.begin(); i != L.end(); ++i) cout << *i << " ";
cout << endl;
return 0;
}

/* OUTPUT: 0 2 0 5 6 */
---------------------------------------------------------------------------
Here is the C example
#include "containers.h"
static int PrintInt(void *pdata,void *extraArgs)
{
int i = *(int *)pdata;
fprintf(extraArgs,"%d ",i);
}
int main(void)
{
List *L;
int data;

L = iList.Create(sizeof(int));

data = 0;
iList.Add(L,&data);
iList.PushFront(L,&data);
data = 2;
iList.InsertAt(L,1,&data);
data = 5;
iList.Add(L,&data);
data = 6;
iList.Add(L,&data);
iList.Apply(L,PrintInt,stdout);
iList.Finalize(L);
}
----------------------------------------------------------------------------

I could have used iterators to print the list but I think using "Apply"
looks better ...

What do you think?
 
Ad

Advertisements

I

Ike Naar

#include "containers.h"
static int PrintInt(void *pdata,void *extraArgs)
{
int i = *(int *)pdata;
fprintf(extraArgs,"%d ",i);
}

PrintInt promises to return an int, but it doesn't.
int main(void)
{
List *L;
int data;

L = iList.Create(sizeof(int));

data = 0;
iList.Add(L,&data);
iList.PushFront(L,&data);
data = 2;
iList.InsertAt(L,1,&data);
data = 5;
iList.Add(L,&data);
data = 6;
iList.Add(L,&data);
iList.Apply(L,PrintInt,stdout);

No terminating newline is printed?
iList.Finalize(L);
}

This

int data = 5;
iList.Add(L, &data);

looks clumsier than

L.push_back(5);

and it's more prone to errors,
for instance, the compiler will accept

long data = 5;
iList.Add(L, &data);

but this may lead to unexpected run-time behaviour on
a machine on which sizeof(int) != sizeof(long)..
 
J

jacob navia

Le 11/05/12 19:54, Ike Naar a écrit :
PrintInt promises to return an int, but it doesn't.


Yes, this is an error. Should return one or other value.
No terminating newline is printed?

No. But it is easy to add one.
This

int data = 5;
iList.Add(L,&data);

looks clumsier than

L.push_back(5);

and it's more prone to errors,
for instance, the compiler will accept

long data = 5;
iList.Add(L,&data);

but this may lead to unexpected run-time behaviour on
a machine on which sizeof(int) != sizeof(long)..

Yes, you can put any value, and you have to keep track of what you are
doing.

A specific interface for a specific data type can be obtained by using
the template file furnished with the sample implementation.

If you do that you obtain compiler checking at compile time.
 
B

Ben Bacarisse

jacob navia said:
Here is a comparison of two source codes that use the C++ STL and the
C containers library (ccl).

It's not clear what the point is. In terms of code clarity and
simplicity, C++ is likely to come out on top in simple comparisons like
this.
First, the C++ example:

// Standard Template Library example

#include <iostream>
#include <list>
using namespace std;

// Simple example uses type int

int main(void)
{
list<int> L;

You can also just initialise the list:

list<int> L = {0, 2, 0, 5, 6};

C libraries will always have live withing C's core language limitations.
L.push_back(0); // Insert a new element at the end
L.push_front(0); // Insert a new element at the beginning
L.insert(++L.begin(),2);// Insert "2" before position of first argument
// (Place before second argument)
L.push_back(5);
L.push_back(6);

list<int>::iterator i;

for(i=L.begin(); i != L.end(); ++i) cout << *i << " ";

Modern C++ has this:

for (int i: L) cout << i << " ";

Nice, yes?
cout << endl;
return 0;
}

/* OUTPUT: 0 2 0 5 6 */
---------------------------------------------------------------------------
Here is the C example
#include "containers.h"
static int PrintInt(void *pdata,void *extraArgs)
{
int i = *(int *)pdata;
fprintf(extraArgs,"%d ",i);
}
int main(void)
{
List *L;
int data;

L = iList.Create(sizeof(int));

data = 0;
iList.Add(L,&data);
iList.PushFront(L,&data);
data = 2;
iList.InsertAt(L,1,&data);
data = 5;
iList.Add(L,&data);
data = 6;
iList.Add(L,&data);
iList.Apply(L,PrintInt,stdout);
iList.Finalize(L);
}

C++ also has an "apply" and, what's more, it doesn't need a top-level
function definition:

for_each(L.begin(), L.end(), [](int i){ cout << i << " "; });
What do you think?

I am not sure what you are really asking.
 
J

jacob navia

Le 11/05/12 21:31, Ben Bacarisse a écrit :
You can also just initialise the list:

list<int> L = {0, 2, 0, 5, 6};


In the C library you can do the equivalent with


int tab[]={0, 2, 0, 5, 6};

iList.InitializeWith(sizeof(int),5,tab);
 
J

jacob navia

Le 11/05/12 21:31, Ben Bacarisse a écrit :
for (int i: L) cout<< i<< " ";

I added this:

#if 0
for(i=L.begin(); i != L.end(); ++i) cout << *i << " ";
cout << endl;
#else
for (int i: L) cout << i << " ";
#endif

and obtained:

~ $ g++ list.cpp
list.cpp: In function ‘int main()’:
list.cpp:25: error: a function-definition is not allowed here before ‘:’
token
list.cpp:27: error: expected primary-expression before ‘return’
list.cpp:27: error: expected `;' before ‘return’
list.cpp:27: error: expected primary-expression before ‘return’
list.cpp:27: error: expected `)' before ‘return’
 
Ad

Advertisements

B

Ben Bacarisse

jacob navia said:
Le 11/05/12 21:31, Ben Bacarisse a écrit :
You can also just initialise the list:

list<int> L = {0, 2, 0, 5, 6};


In the C library you can do the equivalent with


int tab[]={0, 2, 0, 5, 6};

iList.InitializeWith(sizeof(int),5,tab);

The 5 is unfortunate. Did you consider

iList.InitializeWith(sizeof *tab, sizeof tab, tab);

?
 
J

jacob navia

Le 11/05/12 21:31, Ben Bacarisse a écrit :
for_each(L.begin(), L.end(), [](int i){ cout<< i<< " "; });

I added this:
for_each(L.begin(), L.end(), [](int i){ cout << i << " "; });

as you wrote and obtained:

list.cpp:26: error: expected primary-expression before ‘[’ token
list.cpp:26: error: expected primary-expression before ‘]’ token
list.cpp:26: error: expected primary-expression before ‘int’

~$ g++ -v
Using built-in specs.
Target: i686-apple-darwin11
Configured with:
/private/var/tmp/llvmgcc42/llvmgcc42-2336.9~22/src/configure
--disable-checking --enable-werror
--prefix=/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2
--mandir=/share/man --enable-languages=c,objc,c++,obj-c++
--program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/
--with-slibdir=/usr/lib --build=i686-apple-darwin11
--enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2336.9~22/dst-llvmCore/Developer/usr/local
--program-prefix=i686-apple-darwin11- --host=x86_64-apple-darwin11
--target=i686-apple-darwin11 --with-gxx-include-dir=/usr/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00)
 
J

jacob navia

Le 11/05/12 21:31, Ben Bacarisse a écrit :
I am not sure what you are really asking.

Just trying to discuss the two approaches. I am sure
C++ has more "syntactic sugar" than C, but the
two approaches lead to similar code.

I was just asking from feedback about that, maybe improvements
proposals.
 
B

Ben Bacarisse

jacob navia said:
Le 11/05/12 21:31, Ben Bacarisse a écrit :

I added this:

#if 0
for(i=L.begin(); i != L.end(); ++i) cout << *i << " ";
cout << endl;
#else
for (int i: L) cout << i << " ";
#endif

and obtained:

~ $ g++ list.cpp
list.cpp: In function ‘int main()’:
list.cpp:25: error: a function-definition is not allowed here before
‘:’ token
list.cpp:27: error: expected primary-expression before ‘return’
list.cpp:27: error: expected `;' before ‘return’
list.cpp:27: error: expected primary-expression before ‘return’
list.cpp:27: error: expected `)' before ‘return’

Surely that's a question (if it is a question) for comp.lang.c++? But
since I "opened the door" as they say in cheap TV legal dramas -- it's a
new feature, but recent g++ compilers have it (-std=c++0x).
 
B

Ben Bacarisse

jacob navia said:
Le 11/05/12 21:31, Ben Bacarisse a écrit :
for_each(L.begin(), L.end(), [](int i){ cout<< i<< " "; });

I added this:
for_each(L.begin(), L.end(), [](int i){ cout << i << " "; });

as you wrote and obtained:

<snip errors>

It's valid C++, but surely this is not the place to discuss C++ errors?
 
Ad

Advertisements

J

jacob navia

Le 11/05/12 22:02, Ben Bacarisse a écrit :
jacob navia said:
Le 11/05/12 21:31, Ben Bacarisse a écrit :
You can also just initialise the list:

list<int> L = {0, 2, 0, 5, 6};


In the C library you can do the equivalent with


int tab[]={0, 2, 0, 5, 6};

iList.InitializeWith(sizeof(int),5,tab);

The 5 is unfortunate. Did you consider

iList.InitializeWith(sizeof *tab, sizeof tab, tab);

?

The prototype is:
List *InitializeWith(size_t elementSize, size_t n, const void *Data);

You would propose then:
List *InitializeWith(size_t elementSize, size_t datasize, const
void *Data);

where datasize would be the total size of the table, that should be a
multiple of elementSize?

I wote the 5 to be short. Normally I have a
#define SIZEOF(tab) (sizeof(tab)/sizeof(tab[0])
macro somewhere
 
J

jacob navia

Le 11/05/12 22:11, Ben Bacarisse a écrit :
It's valid C++, but surely this is not the place to discuss C++ errors?

Why not? If we are comparing C with C++ code it is ok.

Or did I made a transcription error?
 
C

cartec69

Le 11/05/12 22:11, Ben Bacarisse a écrit :

Why not? If we are comparing C with C++ code it is ok.

Or did I made a transcription error?

The code is valid C++, but makes use of C++11 features which your compiler does not support.
 
B

Ben Bacarisse

jacob navia said:
Le 11/05/12 22:02, Ben Bacarisse a écrit :
jacob navia said:
Le 11/05/12 21:31, Ben Bacarisse a écrit :

You can also just initialise the list:

list<int> L = {0, 2, 0, 5, 6};


In the C library you can do the equivalent with


int tab[]={0, 2, 0, 5, 6};

iList.InitializeWith(sizeof(int),5,tab);

The 5 is unfortunate. Did you consider

iList.InitializeWith(sizeof *tab, sizeof tab, tab);

?

The prototype is:
List *InitializeWith(size_t elementSize, size_t n, const void *Data);

You would propose then:
List *InitializeWith(size_t elementSize, size_t datasize, const
void *Data);

where datasize would be the total size of the table, that should be a
multiple of elementSize?
Yes.

I wote the 5 to be short. Normally I have a
#define SIZEOF(tab) (sizeof(tab)/sizeof(tab[0])
macro somewhere

It all depends on how you think InitializeWith will be used. How often
will the number of elements be more easily available than the number of
bytes? Even if the answer is "almost always", n * sizeof *tab is
simpler that sizeof(tab)/sizeof(tab[0]).
 
I

Ian Collins

Le 11/05/12 21:31, Ben Bacarisse a écrit :

Just trying to discuss the two approaches. I am sure
C++ has more "syntactic sugar" than C, but the
two approaches lead to similar code.

Not really. As Ben demonstrated, the "syntactic sugar" leads to much
more concise and less error prone code. In this case, 2 lines rather
than 18!
I was just asking from feedback about that, maybe improvements
proposals.

What you have is probably the best that can be done within the confines
of C.
 
Ad

Advertisements

B

BartC

jacob navia said:
Here is a comparison of two source codes that use the C++ STL and the
C containers library (ccl).
List *L;
int data;

L = iList.Create(sizeof(int));

data = 0;
iList.Add(L,&data);

Shame you can't use immediate data. Then that line becomes:

ilist.Add(L,0);

Although it might not be much trouble (*in this simple case*) to do:

ilist.Add(L,imm(0));

where imm is "int* imm(int)".

But perhaps in actual use, immediate data isn't used so much.
 
B

Ben Bacarisse

BartC said:
Shame you can't use immediate data. Then that line becomes:

ilist.Add(L,0);

C++ has compound literals which produce lvalues so you can apply & to
the result:

ilist.Add(L, &(int){0});

<snip>
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top