开发者

How can I expose a uniform interface to a template class?

开发者 https://www.devze.com 2023-01-12 02:12 出处:网络
I h开发者_如何转开发ave implemented a templated buffer class like this: template <class T, class Impl>

I h开发者_如何转开发ave implemented a templated buffer class like this:

template <class T, class Impl>
class base_hardware_buffer : Impl
{
public:
    typedef const T& const_reference;
    typedef T* pointer;

    void push_back(reference r)
    {
        // Do some generic operation, call impl when needed
        // ...
    }

    pointer map()
    {
        static_cast<Impl*> (this)->map();
    }

    // ... etc
};

Then I defined two implementations, one for OpenGL and one for DirectX each instantiated in their own dynamic library. For OpenGL:

template <class T>
class glBuffer : base_hardware_buffer<T, glBuffer<T> >
{
public:
    typedef T* pointer;

    pointer map()
    {
        // Actual implementation of map
    }

    // Other implementation specific operation and members go here
};

This is all very nice, and works quite well. Now my problem is that my team mate who is working on the layer above my subsystems wants to implement an algorithm that requires access to the buffers.

How can I give him a uniform access to the buffer without exposing / hard-coding the specific implementations into his code, nor compromising type safety ?


I can explain how I implemented a solution to a similar problem.

Basically I have a "CreateBuffer" function that returns a pointer to a "base" buffer. Then when I call functions on that base buffer they move up to the relevant function.

class BaseBuffer
{
public:
    BaseBuffer(void);
    virtual ~BaseBuffer(void);

    virtual bool Init( GFXHandler* pHandler, unsigned int usage, unsigned int sizeofData )  { return false; }
    virtual bool Shutdown()                                             = 0;

    virtual bool LockBuffer( unsigned int flags, void** ppData )        = 0;
    virtual bool UnlockBuffer()                                         = 0;
};

Now the trick I used, to make sure that the end user doesn't care what the back end implementation of the buffer is, was to make "CreateBuffer" a function pointer. Then when I set up the graphics handler (e.g. GL2Handler) I assign the "GL2CreateBuffer" function to the "CreateBuffer" function pointer.

This way the end-user can just do the following:

BaseBuffer* pBuffer = CreateBuffer();
pBuffer->Init( /*init params*/ );

void* pData = NULL;
pBuffer->LockBuffer( /*lock flags*/, &pData );

memcpy( pData, pOriginalData, sizeOfOriginalData );

pBuffer->UnlockBuffer();

Job done. If a D3D9Handler was created it used the D3D9 implementation if a GL2Handler was created it uses the GL2 implementation etc.

Edit: In answer to your comment wouldn't you just be able to do the following:

template< typename Type > bool LockBuffer( unsigned int flags, Type** pData );

Or do you want to specifically create a class where the only returnable type is the type that it was created with? That would be a tad more complicated as you suddenly have tonnes of different types that would need assigning to the various function pointers as 2 seperate types passed into a template create 2 different functions.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号