Bonjour à tous,
Je ne sais pas si c'est possible, mais j'essaye actuellement de créer un gestionnaire de ressources sous la forme d'une classe template variadique, possédant une méthode templatisée de création d'une ressource d'un type donné, permettant grâce à une expression constante et une assertion statique de vérifier si le type de ressource spécifié est autorisé par la classe (en le comparant aux types du template variadique) et d'interrompre la compilation dans le cas contraire.
Le problème est que je sèche sur le code de la méthode de vérification du type de ressource.
Voici un bout de code (simplifié) pour vous donner une idée :
template<typename... Types>
class Manager
{
public:
template<typename Type, typename... Arguments>
size_t create(Arguments... arguments)
{
static_assert(testTypes<Type>(), "Template function does not allow this type !");
Type* ptr = new Type(Arguments...);
...
return nextId();
}
template<typename Type>
constexpr bool testTypes(); // méthode de vérification du type de ressource
size_t nextId()
{
static size_t id;
return id++;
}
...
};
typedef Manager<sf::Texture, sf::Font, sf::SoundBuffer> ResourceManager;
ResourceManager resources();
resources.create<sf::Texture>(); // Compilation OK
resource.create<sf::Sprite>(); // Compilation ERROR
J'ai quelques pistes pour le code de la méthode testTypes() :
- Pour obtenir le nombre de type passés en template j'utilise -> sizeof...(Types)
- Pour vérifier que deux types sont les mêmes j'utilise -> std::is_same<Type1, Type2>
- Je peut normalement décompresser Types avec l'opérateur ... -> Types...
Maintenant il reste à créer une boucle en méta-programmation (je sais pas si c'est possible),
afin de balayer les types grâce au code :
template <int N, typename... Args> struct ElementType;
template <int N, typename T, typename... Args>
struct ElementType<N, T, Args...> {
static_assert(N < sizeof...(Args) + 1, "overflow!");
typedef typename elementType<N - 1, Args...>::type type;
};
template <typename T, typename... Args>
struct ElementType<0, T, Args...> {
typedef T type;
};
// Par exemple :
elementType<1, sf::Texture, sf::Font, sf::SoundBuffer>::type>::value // donnera le type sf::Font
J'espère que je suis assez clair, et désolé par avance sinon, le sujet est assez difficile je trouve...