[gdal-dev] Simplifying malloc'action with simple templates

Mateusz Loskot mateusz at loskot.net
Sat Jan 9 15:19:31 EST 2010


Folks,

The CPLMalloc and related functions are widely settled, but as
wrappers on std::malloc, they do not make it simpler to use in C++
files, so GDAL code could be more readable. These functions
still require explicit casts.

It is possible to simplify use of them, at least in source files
compiled in C++ mode, by introducing some

/// Option 1 ///////////////////////////////////////////////////////

template <typename T>
T* CPLMallocT(std::size_t const size)
{
    // sizeof(T) * size or al size
    return static_cast<T*>(CPLMalloc(size(T) * size));
}

It's usage gets rid of cast, but still requires type
specified explicitly:

T* p = CPLMallocT<T>(20);

Another variation if flexibility of size of allocation is needed:

template <typename T>
T* CPLMallocT(std::size_t const n, std::size_t const size = sizeof(T))
{
    return static_cast<T*>(CPLMalloc(n * size));
}

int* p1 = CPLMallocT<int>(10);
int* p2 = CPLMallocT<int>(10, 4);

// Option 2 ///////////////////////////////////////////////////////

template <typename T>
void CPLMallocT(T*& ptr, std::size_t const size)
{
    ptr = static_cast<T*>(CPLMalloc(sizeof(T) * size));
}


It removes cast as well as type is resolved by compiler

CPLMallocT(p, 10);


// Option 3 ///////////////////////////////////////////////////////

template <typename T>
T*& CPLMallocT(T*& ptr, std::size_t const size)
{
    ptr = static_cast<T*>(std::malloc(sizeof(T) * size));
    return ptr;
}

This one works as combination of the two above,
removes cast, resolves type, but here pointer is passed
as extra argument to the function:

T* p = 0;

p = CPLMallocT(p, 10);

or

CPLMallocT(p, 10);


IMHO, such functions simplify allocation call, make code more readable,
prevent from spreading large number of casts around by keeping it in
single place. It also may simplify further maintenance, if option 3 is
used, because if T changes, it enough to type of pointer in place of its
declaration, i.e. float* to double* for array.



Yet another version CPLMallocT could take no argument but type only:

template <typename T>
T* CPLMallocT()
{
    return static_cast<T*>(CPLMalloc(size(T)));
}

then allocation like this:

cur = (GDALProxyPoolCacheEntry*) CPLMalloc(sizeof(GDALProxyPoolCacheEntry));

becomes

cur = CPLMallocT<GDALProxyPoolCacheEntry>();


The latter is simpler and intentions are more obvious to
reader - allocate memory for single of object of given type.

If there would be interest in such utilities, I can commit it to
trunk and refactor code.

Best regards,
-- 
Mateusz Loskot, http://mateusz.loskot.net
Charter Member of OSGeo, http://osgeo.org


More information about the gdal-dev mailing list