C++ Code Samples

James Porter

Below are a series of code samples written in C++ that I feel are a good example of my programming abilities. For the most part, these aren't complete programs (i.e. they are not compilable as-is), but instead highlight some of the more interesting portions of my projects. Most of the code below uses the Boost software libraries (I compiled with 1.34.1, but any recent version should suffice.) If you would like to see more details about a particular project, or would like to see more samples in general, please contact me.

Assuming you have Javascript enabled, the code blocks below will be collapsed. Clicking on the +/- buttons to the left of the filenames will expand/collapse the blocks.

C++ with COM/ATL

The code below comes from a project to implement file archive (.tar, .zip, etc.) browsing through the Windows Explorer. Windows XP makes limited use of this with .zip files. Because this project is a Windows shell namespace extension, it was necessary to use COM/ATL, which has a distinctly different style from the C++ Standard's way of programming. In order to make the code more readable and maintainable, I created some utility code to abstract away the more unpleasant bits of COM/ATL.

The example below is responsible for populating a folder view in Windows Explorer. Depending on how EnumObjects is called, Windows may expect different subsets of results (for example "folders only"). The contents of a folder are stored in an STL map, which I then filter using the filter_collection class below. This is then converted to a COM enumeration with a standard ATL template type. The ATLKeepalive class exists to ensure that the filter_collection (and other similar objects not shown here) is not deleted until the COM enumeration is finished with it.

+

ATLKeepalive.h

#pragma once

template<typename T>

class CATLKeepalive :
    public IUnknown
{
public:
    CATLKeepalive(T *data = 0) : data_(data),nrefs_(0)
    {}
    ~CATLKeepalive()
    {
        delete data_;
    }

    STDMETHOD_(ULONG,AddRef) ()
    {
        return ++nrefs_;
    }

    STDMETHOD_(ULONG,Release) ()
    {
        if(--nrefs_ == 0)
        {
            delete this;
            return 0;
        }

        return nrefs_;
    }

    STDMETHOD(QueryInterface) (const IID &iid,void **out)
    {

        if(iid == IID_IUnknown)
        {
            *out = (IUnknown *)this;
            return S_OK;
        }
        else
            return E_NOINTERFACE;
    }
private:
    T *data_;
    ULONG nrefs_;
};

template<typename T>
CATLKeepalive<T> * make_keepalive(T *object)
{
    return new CATLKeepalive<T>(object);
}
...
+

filter_collection.h

#pragma once

#include <boost/iterator/filter_iterator.hpp>

template<typename T,typename P>
class filter_collection
{
public:
    typedef boost::filter_iterator<P,typename T::iterator> iterator;

    typedef boost::filter_iterator<P,typename T::const_iterator> const_iterator;

    filter_collection(T &collection,const P &predicate) : collection_(collection),
        predicate_(predicate)
    {}

    iterator begin()
    {
        return iterator(predicate_,collection_.begin(),collection_.end());
    }

    iterator end()
    {
        return iterator(predicate_,collection_.end(),collection_.end());
    }

    const_iterator begin() const
    {
        return const_iterator(predicate_,collection_.begin(),collection_.end());
    }

    const_iterator end() const
    {
        return const_iterator(predicate_,collection_.end(),collection_.end());
    }
private:
    T &collection_;
    P predicate_;
};
...
+

ArchiverFolder.cpp (excerpts)

#include "ATLKeepalive.h"
#include "filter_collection.h"

struct copy_policy
{
    static void init(LPITEMIDLIST *p)
    {}

    static void destroy(LPITEMIDLIST *p)
    {
        Pidl::release(*p);
    }

    static HRESULT copy(LPITEMIDLIST *to, const tar_file::collection_type::value_type *from)
    {
        *to = Pidl((*from)->name()).extract();
        return S_OK;
    }
};

class enum_filter
{
public:
    enum_filter() : flags_(0) {}
    enum_filter(DWORD flags) : flags_(flags) {}

    bool operator ()(const tar_file::collection_type::value_type &p)
    {
        return (flags_&SHCONTF_NONFOLDERS) || !p->is_file();
    }
private:
    DWORD flags_;
};

typedef filter_collection<sub_file,enum_filter> filter_dir;
typedef CComEnumOnSTL<IEnumIDList,&IID_IEnumIDList,LPITEMIDLIST,copy_policy,
    filter_dir> CEnumIDListImpl;
    
/*
...
*/

// Note: depending on flags, this may return just folders, or just files or whatever;
// this is useful for the treeview on the left of the explorer
STDMETHODIMP CArchiverFolder::EnumObjects(HWND hWnd,DWORD flags,LPENUMIDLIST *ppEnumIDList)
{
    ATLTRACE2(atlTraceCOM,4,L"0x%08x: CArchiverFolder::EnumObjects(%x,%x,...)\n",
        this,hWnd,flags);

    HRESULT hr;
    CComPtr< CComObject<CEnumIDListImpl> > pEnum;

    if(!ppEnumIDList)
        return E_POINTER;
    *ppEnumIDList = 0;

    if(FAILED( hr = CComCreateInstance(pEnum) ))
        return hr;

    filter_dir *coll = new filter_dir(currdir_,enum_filter(flags));

    pEnum->Init(make_keepalive(coll),*coll);
    hr = pEnum->QueryInterface(IID_IEnumIDList,(void **)ppEnumIDList);

    return hr;
}
...

New-style Memory Allocation

This code is an experiment of mine using C++ templates to design an alternative method for dynamic memory allocation in C++. One problem that programmers may encounter when dynamically creating arrays is that a call to "new[] foo" requires that foo be default-constructible. Depending on the situation, this may be undesired or inefficient. The code below allows a programmer to allocate dynamically-sized arrays and supply a generator function for constructing each element. Additionally, this code natively supports smart pointers used in the C++ standard and the Boost libraries (currently only boost::shared_array is supported, but extending support is trivial).

+

alloc.h

#pragma once

#include <boost/type_traits.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/equal_to.hpp>

template<typename T>
class dumb_ptr;

template<typename T,template<typename> class SP = dumb_ptr>
class allocator_;

template<typename T,template<typename> class SP>
class allocator_
{
};

template<typename T>
class allocator_< T[],boost::shared_array >
{
public:
    template<typename f>
    static boost::shared_array<T> alloc(size_t length,f &fcn)
    {
        return boost::shared_array<T>(allocator_<T[]>::alloc(length,fcn));
    }
};

template<typename T>
class allocator_<T[]>
{
public:
    template<typename f>
    static T *alloc(size_t length,f &fcn)
    {
        T *memory = static_cast<T*>(::operator new[](length*sizeof(T)));
        T *curr=memory;
        for(size_t i=0; i<length; i++,curr++)
            fcn(curr,i);
        return memory;
    }
};

template<typename T,template<typename> class U,typename A,typename B>
typename U<typename boost::remove_extent<T>::type>
alloc(const A &a,const B &b)
{
    return allocator_<T,U>::alloc(a,b);
}

template<typename T,typename A,typename B>
typename boost::remove_extent<T>::type *
alloc(const A &a,const B &b)
{
    return allocator_<T>::alloc(a,b);
}
...
+

alloc_test.cpp

#include "alloc.h"

#include <boost/lambda/lambda.hpp>
#include <iostream>
using namespace std;

template<typename T,typename U>
bool test_equal(const T &expected,const U &test,size_t length)
{
    for(size_t i=0; i<length; i++)
    {
        if(expected[i] != test[i])
            return false;
    }
    return true;
}

class foo
{
public:
    foo(int i) : data(i)
    {}
    bool operator !=(const foo &rhs) const
    {
        return data != rhs.data;
    }
private:
    int data;
};

void alloc_foo(foo *f,size_t index)
{
    new(f) foo(static_cast<int>(index));
}

int main()
{
    using namespace boost;
    using namespace boost::lambda;

    size_t expected_int[] = {0,1,2,3,4,5,6,7,8,9};
    foo    expected_foo[] = { foo(0),foo(1),foo(2),foo(3),foo(4),
                              foo(5),foo(6),foo(7),foo(8),foo(9) };

    {
        size_t *test = alloc<size_t[]>(10,*_1 = _2);

        if(test_equal(expected_int,test,10))
            cout << "Test one passed!" << endl;
        else
            cout << "Test one failed!" << endl;

        delete[] test;
    }

    {
        shared_array<size_t> test = alloc<size_t[],shared_array>(10,*_1 = _2);

        if(test_equal(expected_int,test,10))
            cout << "Test two passed!" << endl;
        else
            cout << "Test two failed!" << endl;
    }

    {
        foo *test = alloc<foo[]>(10,alloc_foo);

        if(test_equal(expected_foo,test,10))
            cout << "Test three passed!" << endl;
        else
            cout << "Test three failed!" << endl;

        delete[] test;
    }

    {
        shared_array<foo> test = alloc<foo[],shared_array>(10,alloc_foo);

        if(test_equal(expected_foo,test,10))
            cout << "Test four passed!" << endl;
        else
            cout << "Test four failed!" << endl;
    }
}
...