I'm working on a multi render library. The point of it is to have a swapable backend at runtime to render the same item.
The renderer is given to the window (which is a wrapper over SDL2). Then the window is in charge of drawing a IDrawable, which is a virtual class implemented in a namespace for each backend. The implementation of IDrawable in each namespace got the same tag as the backend, for preventing rendering a drawable with the wrong backend.
Here's the code. I would appreciate some reviews on the architecture; what's good and what's wrong.
Thanks!
#include <string>
#include <iostream>
enum Tag
{
  VK,
  GL
};
class IDrawable
{
    public:
        virtual void draw() = 0;
        virtual Tag getTag() const = 0;        
};
namespace gl
{
class D : public IDrawable
{
    public:
        void draw()
        {
            std::cout << "Drawable gl::D\n";
        }
        Tag getTag() const { return tag; };
    private:
        Tag tag = Tag::GL;
};
}
namespace vk
{
class D : public IDrawable
{
    public:
        void draw()
        {
            std::cout << "Drawable vk::D\n";
        }
        Tag getTag() const { return tag; };
    private:
        Tag tag = Tag::VK;
};
}
class Backend
{
    public:
        virtual void render(IDrawable * d) = 0;
};
class Opengl : public Backend
{
    public:
        void render(IDrawable * d)
        {
            std::cout << "Backend gl\n";
            d->draw();
        }
        Tag getTag() { return tag; };
    private:
        Tag tag = Tag::GL;
};
class Vulkan : public Backend
{
    public:
        void render(IDrawable * d)
        {
            std::cout << "Backend vk\n";
            d->draw();
        }
        Tag getTag() { return tag; };
    private:
        Tag tag = Tag::VK;
};
template <typename T>
class Renderer
{
    static_assert(std::is_base_of<Backend, T>::value, "Backend not valid");
    public:
        void draw(IDrawable * d)
        {
            if(backend.getTag() == d->getTag())
            {
                backend.render(d); 
            }
            else
            {
                std::cout << "Cannot render\n";  
            }
        }
        T backend;    
};
template <typename T>
class Window
{
    public:
        Window(Renderer<T> r) : rend(r) {}
        void draw(IDrawable * d)
        {
            rend.draw(d);   
        }
    private:
        Renderer<T> rend;
};
int main()
{ 
    Renderer<Opengl> a;
    Renderer<Vulkan> b;
    Window w(a);    
    Window k(b);    
    gl::D d1;
    vk::D d2;
    w.draw(&d1);
    k.draw(&d2);
    w.draw(&d2); // Should fail
    return 0;
}