SFML community forums

General => Feature requests => Topic started by: Glocke on November 28, 2014, 03:25:13 pm

Title: Interface for "loadFromFile" (and others)
Post by: Glocke on November 28, 2014, 03:25:13 pm
Hi, an interface for all SFML-classes providing loadFromFile() (and similar) would be great. I'd like to store multiple "Loadables" inside a nested std::map: First key: RTTI using std::type_index(typeid(...)), second key: actual identifier to the resource (e.g. std::string). Because those resources have no common parent class, the final type (which to embedd in the inner std::map) needs to be void* which isn't great for polymorphic stuff.

Btw my map looks currently like this:
std::map<std::type_index,
    std::map<std::string, void*>
>
because I store pointers to different resources. The desired map would look like this:
std::map<std::type_index,
    std::map<std::string, std::unique_ptr<sf::Loadable>>
>

Also this would allow to dynamic_cast instead of static_cast. Casting statically is not helpfull if you're using polymorphism. Else, dynamically casting provides this - but void is not a base class for any of the used types ^^

Why not using a single std::map per resource type? I wrote a private template-based get/set for this entire map. The public interface calls this methods with a concrete type (e.g. sf::Texture). But I don't want to copy'n'paste the entire mechanisms for each new resource type. A "Loadable" interface would help, because I could derive my own resources (such as file streams) from Loadable and use them (just as sf::Texture if implementing Loadable^^) as polymorphic loadables.

Does anyone like this idea?
Title: Re: Interface for "loadFromFile" (and others)
Post by: Strelok on November 28, 2014, 03:48:57 pm
You might want to have a look at Thor (sfml extension)
Title: Re: Interface for "loadFromFile" (and others)
Post by: Nexus on November 28, 2014, 04:21:08 pm
Because those resources have no common parent class, the final type (which to embedd in the inner std::map) needs to be void* which isn't great for polymorphic stuff.
You're thinking the Java way. In C++, types need not have a common base class in order to be used polymorphically. Of course, there are situations where class hierarchies come in handy, but it's not a per-se requirement.

Instead, have a look at type erasure. It's a very powerful C++ concept that combines static and dynamic polymorphism, and it allows you keep type safety without coupling types unnecessarily through inheritance. All this without void* in the API.

Also this would allow to dynamic_cast instead of static_cast. Casting statically is not helpfull if you're using polymorphism.
That is a deterioration. Almost always, dynamic_cast indicates a design flaw, because you're not sure about the dynamic type and have to try it. For downcasting, static_cast should be the default approach, dynamic_cast should be mainly a debug error check in combination with assertions.

As indicated by Strelok, I already wrote a resource-loading abstraction in Thor. See Resources module (http://www.bromeon.ch/libraries/thor/v2.0/doc/group___resources.html) and tutorial (http://www.bromeon.ch/libraries/thor/v2.0/tutorial-resources.html). thor::MultiResourceCache could be interesting for you, as it's a type-erased resource manager. It's currently conceived for shared ownership and automatic duplicate resolution, and thus possibly too complicated for average cases, but I plan to provide a simplified version in the future.
Title: Re: Interface for "loadFromFile" (and others)
Post by: Glocke on November 28, 2014, 04:26:56 pm
You're thinking the Java way.
Well, this is the OOP way - not only the java way ^^

Instead, have a look at type erasure. It's a very powerful C++ concept that combines static and dynamic polymorphism, and it allows you keep type safety without coupling types unnecessarily through inheritance. All this without void* in the API.

I recently discovered dynamically and static casting (to replace old C-style casts). Because of decoupling, my first idea was the stated interface :)

Almost always, dynamic_cast indicates a design flaw, because you're not sure about the dynamic type and have to try it. For downcasting, static_cast should be the default approach, dynamic_cast should be mainly a debug error check in combination with assertions.

Ok thx! :)

About Thor: Yes I already know ;) I'm currently playing around with concepts and ideas.