#include <memory>
#include <unordered_map>
class Resource {
public:
Resource(const std::string&) {}
virtual ~Resource() {}
};
class Texture : public Resource {
public:
int width;
int height;
int channels;
uint8_t* data;
Texture(const std::string& path) : Resource(path) {
load(path);
}
virtual ~Texture() {
// if needed for whatever reason
unload();
}
protected:
void load(const std::string& path) {
// loading logic in here
}
void unload() {
// unloading logic in here
}
};
class ResourceManager {
public:
template<typename T>
std::shared_ptr<T> load(const std::string& path) {
static_assert(std::is_base_of<Resource, T>::value, "T must inherit from Resource");
auto res = resources[path].lock();
if(!res) {
// assuming constructor loads resource
resources[path] = res = std::make_shared<T>(path);
}
auto return_value = std::dynamic_pointer_cast<T>(res);
if(!return_value) {
throw std::runtime_error(std::string("Resource '") + path + "' is already loaded as another type");
}
return return_value;
}
private:
std::unordered_map<std::string, std::weak_ptr<Resource>> resources;
};
int main() {
ResourceManager man;
auto tex = man.load<Texture>("path");
}
I2luY2x1ZGUgPG1lbW9yeT4KI2luY2x1ZGUgPHVub3JkZXJlZF9tYXA+CgpjbGFzcyBSZXNvdXJjZSB7CnB1YmxpYzoKICAgIFJlc291cmNlKGNvbnN0IHN0ZDo6c3RyaW5nJikge30KICAgIHZpcnR1YWwgflJlc291cmNlKCkge30KfTsKCmNsYXNzIFRleHR1cmUgOiBwdWJsaWMgUmVzb3VyY2UgewpwdWJsaWM6CiAgICBpbnQgd2lkdGg7CiAgICBpbnQgaGVpZ2h0OwogICAgaW50IGNoYW5uZWxzOwogICAgdWludDhfdCogZGF0YTsKCiAgICBUZXh0dXJlKGNvbnN0IHN0ZDo6c3RyaW5nJiBwYXRoKSA6IFJlc291cmNlKHBhdGgpIHsKICAgICAgICBsb2FkKHBhdGgpOwogICAgfQoKICAgIHZpcnR1YWwgflRleHR1cmUoKSB7CiAgICAgICAgLy8gaWYgbmVlZGVkIGZvciB3aGF0ZXZlciByZWFzb24KICAgICAgICB1bmxvYWQoKTsKICAgIH0KcHJvdGVjdGVkOgogICAgdm9pZCBsb2FkKGNvbnN0IHN0ZDo6c3RyaW5nJiBwYXRoKSB7CiAgICAgICAgLy8gbG9hZGluZyBsb2dpYyBpbiBoZXJlCiAgICB9CgogICAgdm9pZCB1bmxvYWQoKSB7CiAgICAgICAgLy8gdW5sb2FkaW5nIGxvZ2ljIGluIGhlcmUKICAgIH0KfTsKCmNsYXNzIFJlc291cmNlTWFuYWdlciB7CnB1YmxpYzoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQ+CiAgICBzdGQ6OnNoYXJlZF9wdHI8VD4gbG9hZChjb25zdCBzdGQ6OnN0cmluZyYgcGF0aCkgewogICAgICAgIHN0YXRpY19hc3NlcnQoc3RkOjppc19iYXNlX29mPFJlc291cmNlLCBUPjo6dmFsdWUsICJUIG11c3QgaW5oZXJpdCBmcm9tIFJlc291cmNlIik7CgogICAgICAgIGF1dG8gcmVzID0gcmVzb3VyY2VzW3BhdGhdLmxvY2soKTsKICAgICAgICBpZighcmVzKSB7CiAgICAgICAgICAgIC8vIGFzc3VtaW5nIGNvbnN0cnVjdG9yIGxvYWRzIHJlc291cmNlCiAgICAgICAgICAgIHJlc291cmNlc1twYXRoXSA9IHJlcyA9IHN0ZDo6bWFrZV9zaGFyZWQ8VD4ocGF0aCk7CiAgICAgICAgfQoKICAgICAgICBhdXRvIHJldHVybl92YWx1ZSA9IHN0ZDo6ZHluYW1pY19wb2ludGVyX2Nhc3Q8VD4ocmVzKTsKICAgICAgICBpZighcmV0dXJuX3ZhbHVlKSB7CiAgICAgICAgICAgIHRocm93IHN0ZDo6cnVudGltZV9lcnJvcihzdGQ6OnN0cmluZygiUmVzb3VyY2UgJyIpICsgcGF0aCArICInIGlzIGFscmVhZHkgbG9hZGVkIGFzIGFub3RoZXIgdHlwZSIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0dXJuX3ZhbHVlOwogICAgfQpwcml2YXRlOgogICAgc3RkOjp1bm9yZGVyZWRfbWFwPHN0ZDo6c3RyaW5nLCBzdGQ6OndlYWtfcHRyPFJlc291cmNlPj4gcmVzb3VyY2VzOwp9OwoKaW50IG1haW4oKSB7CglSZXNvdXJjZU1hbmFnZXIgbWFuOwoJYXV0byB0ZXggPSBtYW4ubG9hZDxUZXh0dXJlPigicGF0aCIpOwp9