views:

123

answers:

1

I have a smart pointer type, and would like to construct an object that takes a pointer of that type and a count (dynamically calculated at runtime) and allocates enough memory from the stack to hold that many instances of the object the smart pointer points to. I can't seem to find quite the right syntax to achieve this; is it possible?

Given something like this

template<typename T>
class PointerWrapper
{
public:
    PointerWrapper( T const * _pointer ): m_pointer(_pointer) {}
    typedef T Type;
    T const * m_pointer;
};

template<typename T>
class SomeObject: public NoCopyOrAssign
{
public:
    SomeObject( void * _allocaBuffer, PointerWrapper<T> _source, int _count );
};

I want to do something like this:

void Test( PointerWrapper<int> _array, int _count )
{
    SomeObject<int> object = MakeSomeObject( _array, _count );
    // do some work with object
};

Code invoking the following macro doesn't compile, because the compiler cannot deduce SomeObject's template parameter from _wrappedPtr so complains that the template parameter is missing:

#define MakeSomeObject(_wrappedPtr, _runtimeCount) \
    SomeObject(alloca(sizeof(_wrappedPtr::Type)*_runtimeCount), \
                    _wrappedPtr, _runtimeCount)

If a function templated on the pointer wrapper type is used, although the compiler can deduce the types implicitly, code invoking it doesn't compile because SomeObject deliberately defines but does not implement a copy constructor or assignment operator; even if it did compile it would not do the right thing because the memory provided by alloca() would immediately go out of scope:

template<typename WrappedT>
SomeObject<typename WrappedT::Type> MakeSomeObject
    ( WrappedT _pointer, uint _runtimeCount )
{
    return SomeObject<typename WrappedT::Type>
     ( alloca(sizeof(typename WrappedT::Type)*_runtimeCount),
      _pointer, _runtimeCount );
}

I'd like to avoid passing the type into the macro as an argument since in the real code this would result in quite lengthy, hard-to-read statements at the point of use, however I guess that is a fallback if nothing better is possible.

+1  A: 

Never mind, worked it out; the trick was to combine both approaches:

template<typename WrappedT>
SomeObject<typename WrappedT::Type> _MakeSomeObject
    ( void *_buffer, WrappedT _pointer, int _runtimeCount )
{
    return SomeObject<typename WrappedT::Type>
        ( _buffer, _pointer, _runtimeCount );
}

template<typename WrappedT>
int SizeT( WrappedT const _dummy ) { return sizeof(typename WrappedT::Type); }

#define MakeSomeObject(_wrappedPtr, _runtimeCount) \
        _MakeSomeObject( alloca(SizeT(_wrappedPtr)*_runtimeCount), \
             _wrappedPtr, _runtimeCount )
moonshadow