(Précision : ce message est aussi présent sur le forum C d'OC, ne faites pas les étonnés).
Salut!
A force de voir les débutants manipuler SDL en C++ comme on le ferait en C (alors que ce n'est pas safe dans le premier). Leur conseiller d'écrire un wrapper (ce qu'ils ne font pas bien entendu). Je me suis dit que coder moi-même le wrapper et le proposer en DL libre sur le forum, ça pourrait être une bonne idée (et un bon moyen de faire remarquer aux méchants débutants qu'ils sont inexcusables et voués à l'enfer, bref passons).
Il m'a semblé cohérent de décréter que ma classe SDL::Surface avait une sémantique d'entité (si vous ne savez pas ce qu'est une classe, vous pouvez passer au paragraphe suivant, ce n'est pas le coeur du problème, juste une discussion possible pour ceux qui verraient un problème côté conception). Et donc, qu'elle aurait un constructeur de copie / opérateur d'affectation par copie (elle possède également la move-semantic).
Or qui dit constructeur de copie, dit copie de la SDL::Surface, qui se doit d'être "const" en C++. Et c'est là que les problèmes arrivent.
Le moyen le plus simple de faire une copie d'une SDL_Surface (la structure C SDL), c'est de faire "création de la bonne taille + SDL_BlitSurface". Or, cette fonction prend en paramètre la surface source comme "non-const". Après quelques recherches, il s'avère que du point de vue de l'implémentation de SDL, c'est un choix voulu et assumé (on pourrait parler de sa justification d'un point de vue conception, m'enfin …).
Je me pose donc la question de ce qui serait le moins moche :
- supprimer le "const" de la surface à coup de cast : cette méthode me plaît moyen, en particulier parce que le non-const est justifié, la structure interne de la surface source est réellement modifiée.
- tempérer la solution précédente en utilisant un wrapping de la fonction de blit pour isoler au maximum de downcast, mais c'eest toujours pas très joli.
- faire une deep-copy de la structure SDL_Surface : cette méthode me conviendrait mais les chances de faire une connerie sont monumentales, manipulation d'un void* + dimensions + pitch(?) + BytePerPixel, obligé de faire également une deep-copy du pixel format, etc …
- une autre solution qui existe et que je n'ai pas vu ?*
(*) j'ai déjà regardé du côté de CreateRGBSurfaceFrom mais la lib ne fait pas de copie du pixel data donc ça veut dire une étape de manipulation supplémentaire et une implémentation différente au sein d'une même classe, cette solution est vraiment celle que je veux éviter à tout prix.
Bref. Des idées ?