Click here to Skip to main content
Click here to Skip to main content

What's New in ACF 0.3

, 23 Jun 2004
Rate this:
Please Sign up or sign in to vote.
This article introduces what's new in ACF (Another C++ Framework) version 0.3.

Introduction

ACF (Another C++ Framework) is a C++ framework designed to bring the power and RAD of the .NET framework to standard C++. The overall vision of version 0.3 is to deliver a more robust and ready to use Corlib.

1. Type system

Basic RTTI support

ACF 0.3 supports basic RTTI through Type, Object::GetType(), and macro TYPEOF(T). The implementation is based on standard C++ RTTI, namely type_info and typeid. Currently, there is no plan to support advanced reflection functionalities in the .NET framework (e.g., calling a method at runtime).

The following sample code shows how to use GetType and TYPEOF.

ObjectPtr obj = str(L"hello");
bool equals = (obj->GetType() == TYPEOF(String));

Following is the equivalent code in C#:

object obj = "hello";
bool equals = (obj.GetType() == typeof(string));

Value types boxing/unboxing unification

In ACF 0.3, all value types are boxed to type Boxed<T> (e.g.: Boxed<Int32>, Boxed<DateTime>) through template specialization for consistency purpose. For example, the following code checks whether an object is int, and if so, reads its value:

ObjectPtr obj = box(10);
...
Boxed<Int32>* intObj = dynamic_cast<Boxed<Int32>*>(obj.Pointer);
if (intObj != null) {
    int n = intObj->Value;
}

Of course, the example can also be written as follows, if try/catch is preferred and you don't need to change the value of the object:

ObjectPtr obj = box(10);
...
try {
    int n = unbox<int>(obj); // actually calls unbox<Int32>(obj)
}
catch (...) {
}

2. Base types parsing and formatting

Base types parsing and formatting are updated in ACF 0.3 (however, currently there is no support for cultures). For example, the following code shows how to format integers using various formats:

Int32 n = 123456789;
Console::WriteLine(n.ToString(L"C")); // $123,456,789.00
Console::WriteLine(n.ToString(L"E")); // 1.234568E+008
Console::WriteLine(n.ToString(L"P")); // 12,345,678,900.00%
Console::WriteLine(n.ToString(L"N")); // 123,456,789.00
Console::WriteLine(n.ToString(L"F")); // 123456789.00

The following function formats file sizes as shown in Windows Explorer (e.g., "3,012 KB"):

StringPtr FormatFileSize(int64 size) {
    Int64 kb = size / 1024;
    if (size % 1024 != 0)
        kb++;
    return kb.ToString(L"N0") + str(L" KB");
}

3. Arrays and collections

Multi-dimensional arrays

ACF 0.3 supports multi-dimensional arrays. The array class definition is as follows:

template <typename T, int R> // R: array rank, default to 1
class Array : ... {
    Array(int (&lengths)[R]);
    T GetValue(int (&indices)[R]);
    void SetValue(InArgType value, int (&indices)[R]);
    ...
};

// specialization for 1D arrays
template <typename T>
class Array<T, 1> : ... {
    Array(int length);
    T GetValue(int index);
    void SetValue(InArgType value, int index);

    static int BinarySearch(Array<T, 1>* array, InArgType value, 
        IComparer<T>* comparer = null);
    static void Sort(Array<T, 1>* array, 
               IComparer<T>* comparer = null);
    ...
};

// specialization for 2D arrays
template <typename T>
class Array<T, 2> : ... {
    Array(int length1, int length2);
    T GetValue(int index1, int index2);
    void SetValue(InArgType value, int index1, int index2);
    ...
};

...

As you can see, the implementation uses template partial specialization for various array ranks (especially for single dimensional arrays). This is because certain methods, such as BinarySearch, work only on single dimensional arrays. In C#, if you call BinarySearch on a two dimensional array, it compiles OK but will throw a RankException at runtime. In ACF, this will be a compile-time error.

The following sample code shows how to use three dimensional arrays:

RefPtr<Array<int, 3> > array3D = new Array<int, 3>(10, 20, 30);
array3D->SetValue(100, 0, 0, 0);

Following is the equivalent code in C#:

int[,,,] array3D = new int[10, 20, 30];
array3D[0, 0, 0] = 100; // or array3D.SetValue(100, 0, 0, 0);

Comparing and sorting (esp. case insensitive)

ACF 0.3 supports comparing interfaces and classes like IComparer<T>, Comparer<T>, and StringComparer (which are introduced in .NET 2.0). For example, the following sample code sorts a string array using case insensitive invariant culture:

RefPtr<Array<StringPtr> > array = 
  Array<StringPtr>::Build(str(L"hello"), str(L"world"));
Array<StringPtr>::Sort(array, 
  StringComparer::get_InvariantCultureIgnoreCase());

Following is the equivalent code in C#:

string[] array = new string[] { "hello", "world" };
Array.Sort(array, StringComparer.InvariantCultureIgnoreCase);

The following sample code shows how to use case insensitive hash table:

RefPtr<Dictionary<StringPtr, int> > dict = 
  new Dictionary<StringPtr, int>(StringComparer::get_InvariantCultureIgnoreCase());
dict->Item[str(L"Test")] = 10;
int n = dict->Item[str(L"test")];

Following is the equivalent code in C#:

Dictionary<string, int> dict = 
    new Dictionary<string, int>(StringComparer.InvariantCultureIgnoreCase);
dict["Test"] = 10;
int n = dict["test"];

4. Registry support

ACF 0.3 provides support for accessing Windows registry (under namespace Acf::Microsoft::Win32). The RegViewer sample application shows how to use the registry classes.

For example, the following code shows how to respond to TVN_ITEMEXPANDING notification and expand the tree view node (exception handling code omitted):

void CRegViewerDlg::OnTvnItemexpandingTree1(NMHDR *pNMHDR, LRESULT *pResult) {
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    *pResult = 0;

    if (pNMTreeView->action == TVE_EXPAND && 
        (pNMTreeView->itemNew.state & TVIS_EXPANDEDONCE) == 0) {
        RegistryKey* parentKey = 
          reinterpret_cast<RegistryKey*>(pNMTreeView->itemNew.lParam);

        // Get the subkey names and sort them
        RefPtr<Array<StringPtr> > subKeyNames = parentKey->GetSubKeyNames();
        Array<StringPtr>::Sort(subKeyNames, 
            StringComparer::get_InvariantCultureIgnoreCase());

        // Add the subkeys to the tree view
        FOREACH (StringPtr, keyName, subKeyNames) {
            RegistryKeyPtr subKey = parentKey->OpenSubKey(keyName);
            InsertTreeNode(subKey, keyName, 
                             pNMTreeView->itemNew.hItem, TVI_LAST);
        }
    }
}

The following code adds keys to the tree view:

HTREEITEM CRegViewerDlg::InsertTreeNode(RegistryKey* key, String* name, 
                               HTREEITEM hParent, HTREEITEM hInsertAfter) {
    key->AddRef(); // we'll release it in TVN_DELETEITEM

    CW2T nameT(name->GetCString());

    TVINSERTSTRUCT tvi;
    memset(&tvi, 0, sizeof(tvi));
    tvi.hParent = hParent;
    tvi.hInsertAfter = hInsertAfter;
    tvi.item.mask = TVIF_TEXT | TVIF_CHILDREN | TVIF_PARAM;
    tvi.item.pszText = nameT;
    tvi.item.lParam = reinterpret_cast<LPARAM>(key);
    tvi.item.cChildren = key->SubKeyCount;

    return this->_treeCtrl.InsertItem(&tvi);
}

As you can see, we should call AddRef when adding the key to the tree view to comply with our reference counting rules. We should release it in the TVN_DELETEITEM notification:

void CRegViewerDlg::OnTvnDeleteitemTree1(NMHDR* pNMHDR, LRESULT* pResult) {
    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    *pResult = 0;

    RegistryKey* key = 
      reinterpret_cast<RegistryKey*>(pNMTreeView->itemOld.lParam);
    key->Release();
}

5. Other minor updates and clean-up

For example, Directory::GetLogicalDrives.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Yingle Jia
Web Developer
China China
Yingle Jia is a software engineer located in Beijing, China. He currently works at IBM CSDL (China Software Development Lab). His interests include C++/COM/C#/.NET/XML, etc. He likes coding and writing.
 
He is the creator of ACF (Another C++ Framework) project. See http://acfproj.sourceforge.net/.
 
He also has a blog at http://blogs.wwwcoder.com/yljia/

Comments and Discussions

 
GeneralGarbage Collection Pinmembergyar1-Jul-04 7:04 
GeneralRe: Garbage Collection PinsussYingle Jia1-Jul-04 19:04 
GeneralRe: Garbage Collection Pinmembergyar2-Jul-04 15:03 
QuestionWhere is the project zip? Pinmemberggerules24-Jun-04 11:00 
AnswerRe: Where is the project zip? PinmemberDandy Cheung24-Jun-04 16:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.1411022.1 | Last Updated 24 Jun 2004
Article Copyright 2004 by Yingle Jia
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid