#include <iostream>
#include <cassert>

struct ResourceHandle
{  
    typedef unsigned Id;
    static const Id NULL_ID = 0;
    ResourceHandle() : id(NULL_ID) {}
    
    bool isNull() const
    { return id == NULL_ID; }
    
    Id id;
};

template <typename THandle, typename THandleInterface>
struct Resource
{
    typedef THandle Handle;
    typedef THandleInterface HandleInterface;
    
    HandleInterface* getInterface() const { return _interface; }
    void setInterface(HandleInterface* interface) { assert(!getHandle().isNull()); // should not work if handle is NOT null
                                            _interface = interface; }
                                            
    const Handle& getHandle() const
    { return _handle; }
    
protected:

    typedef Resource<THandle, THandleInterface> Base;
    
    Resource(HandleInterface* interface) : _interface(interface) {}
    
    Handle _handle;
    
private:
    
    HandleInterface* _interface;
};

// example:

struct Image
{ /* ... */ };

struct TextureHandle : ResourceHandle
{
    unsigned int width, height, depth;
};

struct TextureHandleInterface
{
    virtual bool load(TextureHandle&, const Image&) = 0;
    virtual void destroy(TextureHandle&) = 0;
    virtual Image getImageData(const TextureHandle&) const = 0;
};

struct Texture : Resource<TextureHandle, TextureHandleInterface>
{
    Texture(HandleInterface* interface) : Base(interface) {}
    
    bool load(const Image& image) { return getInterface()->load(_handle, image); }
    void destroy() { return getInterface()->destroy(_handle); }
    Image getImageData() const { return getInterface()->getImageData(_handle); }
};

class OglTextureInterface : public TextureHandleInterface
{
public:
    
    OglTextureInterface()
    {
        _nextId = 0;
    }
    
    virtual bool load(TextureHandle& texture, const Image&)
    {
        std::cout << "Loading texture: " << &texture;
        texture.id = _nextId++;
        return true;
    }
    
    virtual void destroy(TextureHandle& texture) 
    {
        std::cout << "Destroying texture: " << &texture;
    }
    
    virtual Image getImageData(const TextureHandle&) const 
    {
        return Image();
    }
    
private:

    ResourceHandle::Id _nextId;
};

int main(int argc, char* argv[])
{
    OglTextureInterface interface;
    Texture texture(&interface);
    
    texture.load(Image());
    
    
    std::cout << "\nTexture ID: " << texture.getHandle().id << '\n';
    
    return 0;
}