I am wondering, how can I improve this simple MissingResource
exception class? I am using it in my simple game.
template <typename Resource>
class MissingResource : public std::exception {
std::string_view fileName{};
std::string_view msg{};
public:
MissingResource() = default;
MissingResource(std::string_view fileName)
: fileName{fileName}
{
initMsg<Resource>();
}
template <typename T>
void initMsg() {
msg = "Failed loading resource: "
"{ Type: " + std::string(typeid(Resource).name()) + ", "
"File name: " + fileName.data() + " }";
}
virtual const char* what() const noexcept override {
return msg.data();
}
};
Throw usage:
template <typename Key, typename Resource>
#if (__cplusplus == 202002L)
requires Mappable<Key>
#endif
class ResourceHolder {
std::unordered_map<Key, std::unique_ptr<Resource>> resources;
std::string resourcesDir;
public:
explicit ResourceHolder(std::string_view resourcesDir = "../resources/")
: resourcesDir{std::move(resourcesDir)}
{}
template <typename... Args>
void insert(const Key& key, std::string_view fileName, Args&&... args) {
auto resPtr = std::make_unique<Resource>();
bool loaded{};
if constexpr (std::is_same<Resource, sf::Music>()) {
loaded = resPtr->openFromFile(resourcesDir + fileName.data(), std::forward<Args>(args)...);
} else {
loaded = resPtr->loadFromFile(resourcesDir + fileName.data(), std::forward<Args>(args)...);
}
/** Called here */
if (!loaded) {
throw MissingResource<Resource>(fileName);
}
resources.emplace(key, std::move(resPtr));
}
Try-Catch usage:
ResourceManager::ResourceManager() {
try {
loadResources();
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
std::exit(EXIT_FAILURE);
}
}
Exemplary error message:
what(): Failed loading resource: { Type: N2sf11SoundBufferE, File name: Death.wav }
P.S: If you see some smelly code or have doubts or found any kind of other mistakes, I would be looking forward to knowing them. Thanks!
std::runtime_error
in this case.std::exception
is an abstract class, and he wants to overridewhat
basically. Maybe he can remove some code if inheriting fromstd::runtime_error
(removing string member), but I think the class is clear enough as it is. Inheritance chains don't need to be unnecessarily long. \$\endgroup\$ – Mikael H Jun 19 '20 at 10:29