Как я могу предоставить единый интерфейс для шаблона шаблона? - PullRequest
1 голос
/ 19 августа 2010

Я реализовал шаблонный класс буфера следующим образом:

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
};

Затем я определил две реализации, одну для OpenGL и одну для DirectX, каждая из которых была создана в своей собственной динамической библиотеке.Для 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
};

Это все очень хорошо, и работает довольно хорошо.Теперь моя проблема в том, что мой напарник, который работает над уровнем выше моей подсистемы, хочет реализовать алгоритм, который требует доступа к буферам.

Как я могу дать ему одинаковый доступ к буферу, не подвергая / hard-Кодирование конкретных реализаций в своем коде, а также не ставит под угрозу безопасность типов?

1 Ответ

0 голосов
/ 20 августа 2010

Я могу объяснить, как я реализовал решение аналогичной проблемы.

В основном у меня есть функция "CreateBuffer", которая возвращает указатель на "базовый" буфер. Затем, когда я вызываю функции из этого базового буфера, они переходят к соответствующей функции.

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;
};

Теперь уловка, которую я использовал, чтобы убедиться, что конечному пользователю все равно, как реализована внутренняя реализация буфера, заключалась в том, чтобы сделать CreateBuffer указателем на функцию. Затем, когда я устанавливаю графический обработчик (например, GL2Handler), я назначаю функцию «GL2CreateBuffer» указателю функции «CreateBuffer».

Таким образом, конечный пользователь может просто сделать следующее:

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

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

memcpy( pData, pOriginalData, sizeOfOriginalData );

pBuffer->UnlockBuffer();

Работа выполнена. Если был создан D3D9Handler, он использовал реализацию D3D9, если был создан GL2Handler, он использовал реализацию GL2 и т. Д.

Редактировать: В ответ на ваш комментарий вы не сможете сделать следующее:

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

Или вы хотите специально создать класс, в котором единственным возвращаемым типом является тип, с которым он был создан? Это было бы немного сложнее, поскольку у вас внезапно появилось множество различных типов, которые потребовали бы назначения различным указателям на функции, поскольку два отдельных типа, передаваемых в шаблон, создают две разные функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...