Friday, October 31, 2008

Java Generic Array Creation

Consider the following code :-


class A<E>
{
public A<E>[] array = new A<E>[4];
}


We will get the following compilation error :-

C:\Projects\Main\src\test\Main.java:24: generic array creation


This is due to erasure in generic http://en.wikipedia.org/wiki/Generics_in_Java, which posts a limit to generic array creation.

The workaround is simple. Here is the fixed code :-


class A<E>
{
@SuppressWarnings("unchecked")
public A<E>[] array = new A[4];
}


However, is it safe to do so? Yes. Generics are checked at compile-time for type correctness. We still able to receive "protection" from the above code. Consider the following :-


public class Main {
public static void main(String[] args) {
A<String> a = new A<String>();
// We try to do some stupid thing here.
a.array[0] = 0;
}
}


The compiler will prevent us to do "stupid" thing by flagging us :-

C:\Projects\Main\src\test\Main.java:32: incompatible types


We are being protected :)

Saturday, October 18, 2008

Compile Open Source Edition QT4.4.3 using Microsoft Visual C++ 2008 Express Edition

It is pretty simple and straight forward to compile open source edition QT4.4.3 using Microsoft Visual C++ 2008 Express Edition

1) Add the following path "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin" into environment variable.

2) cd C:\QT\4.4.3 (Assume you extract out qt-win-opensource-src-4.4.3.zip there)

3) vcvars32.bat

4) configure -platform win32-msvc2008

5) nmake

Done :)

Wednesday, October 15, 2008

String As Template Parameter

Consider the following template function :-


template<const char* T>
void fun()
{
}


How can we make a call to this function?

"Easy!". I heard you are saying that way. Just :-


const char* s0 = "hello world";

int main()
{

fun<s0>();
return 0;
}


However, when performing compilation, our Visual C++ gives us the following compilation error :-

error C2975: 'T' : invalid template argument for 'fun', expected compile-time constant expression

"Arghh, I know that, just provide array of character, as its length is known during compile-time."

(Note : To understand the difference among char pointer and char array, please refer to http://support.microsoft.com/kb/44463. We may use sizeof operator, which is evaluated during compile-time, to retrieve string length information from char array, but not char pointer)

So, we would have something like this :-


const char s0[] = "hello world";

int main()
{

fun<s0>();
return 0;
}


OK. It should compiled then, isn't it? However, our compiler again make a complain :-

error C2970: 'fun' : template parameter 'T' : 's0' : an expression involving objects with internal linkage cannot be used as a non-type argument

I heard you are crying.

Take a rest for a while. Let's forget string template parameter at this moment. Let us take a look into internal linkage and external linkage. Consider the following two files :-


// Module0.cpp
////////////////////
//Internal Linkage//
////////////////////

// Constant pointer which is having internal linkage
char* const s0 = "hello";

// Constant string with constant pointer is haing internal linkage
const char* const s1 = "hello";

// Internal linkage
const char s3[] = "hello";


and


// Module1.cpp
////////////////////
//Internal Linkage//
////////////////////

// Constant pointer which is having internal linkage
char* const s0 = "hello";

// Constant string with constant pointer is haing internal linkage
const char* const s1 = "hello";

// Internal linkage
const char s3[] = "hello";


There are two modules. Two modules are having the same set of variable names. However, when we compile and link them together, everything just work fine. This is because they are having internal linkage. The variables are only visible within their own translator unit (object file). No conflict will occur.

How about external linkage? Consider the following two files again.


// Module0.cpp
////////////////////
//External Linkage//
////////////////////

// Constant string which is having external linkage (Early detected during compiled time)
const char* s0 = "hello";

// String with external linkage
char* s1 = "hello";


and


// Module1.cpp
////////////////////
//External Linkage//
////////////////////

// Constant string which is having external linkage
const char* s0 = "hello";

// String with external linkage
char* s1 = "hello";


We will fail during linking time. The external linkage variables are visible among other translator units. Hence, compiler will complain duplicated variable's names being detected.

Till now, I guess you roughly have an idea on why the char array is not being accepted by template function. char array is having internal linkage by default. We need to explicit state that we want external linkage.

Please do not ask me why it must be external linkage. Ask Bjarne Stroustrup. His 14.3.2 "The C++ Programming Language" states that way.

The final piece of code to solve this problem is :-


extern const char s0[] = "hello world";

int main()
{

fun<s0>();
return 0;
}

Sunday, October 12, 2008

Template Version memcpy

I came across the following code snippet few days ago


template<int size, typename T>
void template_memcpy(T* dest, const T* src)
{
struct type {
T data[size];
};

*reinterpret_cast<type *>(dest) = *reinterpret_cast<const type *>(src);
}


The code seems pretty cool. It performs conventional memcpy, by depending on compiler generated code.

I made a test on Visual C++ 2008 compiler, to see whether the generated code from template_memcpy, is as good as conventional c-style memcpy.

Our source is a 31 bytes char array. Take a look on the conventional c-style memcpy source code, together with its disassembly.


memcpy(dest, src, sizeof(src));
00241053 B9 07 00 00 00 mov ecx,7
00241058 8D 74 24 1C lea esi,[esp+1Ch]
0024105C 8B FB mov edi,ebx
0024105E F3 A5 rep movs dword ptr es:[edi],dword ptr [esi]
00241060 66 A5 movs word ptr es:[edi],word ptr [esi]
00241062 A4 movs byte ptr es:[edi],byte ptr [esi]


From the assembly code, we know that CPU performs

1) Move double word (4 bytes) from source to destination memory 7 times.
2) Move word (2 bytes) from source to destination memory 1 time.
3) Move byte from source to destination memory 1 time.

How about the generated code for template_memcpy?


template_memcpy<sizeof(src)>(dest, src);
002410C7 B9 07 00 00 00 mov ecx,7
002410CC 8D 74 24 1C lea esi,[esp+1Ch]
002410D0 8B FB mov edi,ebx
002410D2 F3 A5 rep movs dword ptr es:[edi],dword ptr [esi]
002410D4 66 A5 movs word ptr es:[edi],word ptr [esi]
002410D6 A4 movs byte ptr es:[edi],byte ptr [esi]


See. template_memcpy is as good as conventional memcpy, isn't it?

OK. So, why do we choose template_memcpy over memcpy?

template_memcpy with come in handy, when you try to perform copy on array of objects.

Instead of :-


MyObject src[100];
MyObject *dest = new MyObject[sizeof(src) / sizeof(src[0])];

for(int i=0; i<(sizeof(src) / sizeof(src[0])); i++) {
dest[i] = src[i];
}

delete[] dest;


We may :-


MyObject src[100];
MyObject *dest = new MyObject[sizeof(src) / sizeof(src[0])];

template_memcpy<sizeof(src) / sizeof(src[0])>(dest, src);

delete[] dest;


The code seems cleaner, isn't it?

Of course, there is a shortcoming for template_memcpy. It only support memory size, which is known during compiled time :)

Followers