// Create the button texture (transparent) and set it as render target
m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height);
if (m_Texture == nullptr)
{
throw Exception(ERROR_SDL_STR);
}
if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0)
{
cleanup();
throw Exception(ERROR_SDL_STR);
}
if (SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0)
{
cleanup();
throw Exception(ERROR_SDL_STR);
}
if (SDL_RenderClear(Game::get()->renderer()) != 0)
{
cleanup();
throw Exception(ERROR_SDL_STR);
}
if (SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0)
{
cleanup();
throw Exception(ERROR_SDL_STR);
}
Comme vous le voyez, on a 5 lignes de code utiles pour une vingtaine de lignes de vérification. Au début, ça va, puis ça facilite bien le débogage. Mais à un moment ça devient pénible à lire (sans parler du fait que ce n'est pas beau ).bool fonction1(void)
{
// Create the button texture (transparent) and set it as render target
m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height);
if (m_Texture == nullptr) return false;
if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0) return false;
if (SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0) return false;
if (SDL_RenderClear(Game::get()->renderer()) != 0) return false;
if (SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0) return false;
return true;
}
void function2(void)
{
if (!fonction1)
{
cleanup();
throw Exception(ERROR_SDL_STR);
}
}
Le principe est du C pur (et n'est pas Ximoon-compliant ), tu dois pouvoir faire ça plus élégamment en C++ avec des exceptions, mais comme c'est pas mon domaine je laisse quelqu'un d'autre proposer une meilleure solution // Create the button texture (transparent) and set it as render target
m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height);
if (m_Texture == nullptr)
throw Exception(ERROR_SDL_STR);
if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0
|| SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0
|| SDL_RenderClear(Game::get()->renderer()) != 0
|| SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0)
{
cleanup();
throw Exception(ERROR_SDL_STR);
}
void myassert(int i) : throws Exception { if ( i != 0 ) { cleanup(); throw Exception(ERROR_SDL_STR); } } myassert(SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND)) ; myassert(SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0)) ; myassert(SDL_RenderClear(Game::get()->renderer())) ; myassert(SDL_SetRenderTarget(Game::get()->renderer(), m_Texture)) ;(Tu peux d'ailleurs utiliser un mécanisme d'assertion déjà défini, potentiellement en debug uniquement (définition via des macros)
bool fonction1(void)
{
bool ret = false;
// Create the button texture (transparent) and set it as render target
m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height);
if (m_Texture == nullptr) goto exit;
if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0) goto exit;
if (SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0) goto exit;
if (SDL_RenderClear(Game::get()->renderer()) != 0) goto exit;
if (SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0) goto exit;
ret = true;
exit:
return ret;
}
Uther (./1340) :Ça peut aider quand il y a de l'analyse automatique de code, me semble-t-il
Perso, je trouve que le grand dogme du "return unique" n'apporte rien, particulièrement si on fait des goto pour y arriver. Au final ça revient exactement à la même chose.
Folco (./1329) :Personnellement, je mettrais:
Voici un bout de mon code du moment :// Create the button texture (transparent) and set it as render target m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height); if (m_Texture == nullptr) { throw Exception(ERROR_SDL_STR); } if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0) { cleanup(); throw Exception(ERROR_SDL_STR); } if (SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0) { cleanup(); throw Exception(ERROR_SDL_STR); } if (SDL_RenderClear(Game::get()->renderer()) != 0) { cleanup(); throw Exception(ERROR_SDL_STR); } if (SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0) { cleanup(); throw Exception(ERROR_SDL_STR); }
Comme vous le voyez, on a 5 lignes de code utiles pour une vingtaine de lignes de vérification. Au début, ça va, puis ça facilite bien le débogage. Mais à un moment ça devient pénible à lire (sans parler du fait que ce n'est pas beau ).Comment s'y prendre pour alléger les choses ?
// Create the button texture (transparent) and set it as render target
m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height);
if (m_Texture == nullptr) throw Exception(ERROR_SDL_STR);
if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0)
{
error:
cleanup();
throw Exception(ERROR_SDL_STR);
}
if (SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0) goto error;
if (SDL_RenderClear(Game::get()->renderer()) != 0) goto error;
if (SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0) goto error;
voire: // Create the button texture (transparent) and set it as render target
m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height);
if (m_Texture == nullptr) {
throw_exception:
throw Exception(ERROR_SDL_STR);
}
if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0) {
error:
cleanup();
goto throw_exception;
}
if (SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0) goto error;
if (SDL_RenderClear(Game::get()->renderer()) != 0) goto error;
if (SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0) goto error;
Zerosquare (./1330) :Bah, c'est un cas classique pour un try … finally. Le mot-clé finally n'existe pas en C++, mais peut-être facilement émulé par une macro. (Seul inconvénient: il faut utiliser des parenthèses en guise d'accolades, parce que la macro doit dupliquer le code à l'intérieur de l'accolade.) Donc une solution plus C++-compliant (mais pas encore tout à fait, je vais y venir par la suite) est:
Le principe est du C pur (et n'est pas Ximoon-compliant ), tu dois pouvoir faire ça plus élégamment en C++ avec des exceptions, mais comme c'est pas mon domaine je laisse quelqu'un d'autre proposer une meilleure solution
#define FINALLY(cleanups) catch(...) {cleanups throw;} {cleanups}
// Create the button texture (transparent) and set it as render target
m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height);
if (m_Texture == nullptr) throw Exception(ERROR_SDL_STR);
try {
if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0) throw Exception(ERROR_SDL_STR);
if (SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0) throw Exception(ERROR_SDL_STR);
if (SDL_RenderClear(Game::get()->renderer()) != 0) throw Exception(ERROR_SDL_STR);
if (SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0) throw Exception(ERROR_SDL_STR);
} FINALLY(
cleanup();
)
Godzil (./1336) :
./1330: C'est moche plusieurs return dans une seul fonctionbool fonction1(void) { bool ret = false; // Create the button texture (transparent) and set it as render target m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height); if (m_Texture == nullptr) goto exit; if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0) goto exit; if (SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0) goto exit; if (SDL_RenderClear(Game::get()->renderer()) != 0) goto exit; if (SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0) goto exit; ret = true; exit: return ret; }
Voila c'est mieux
Folco (./1345) :Tu peux utiliser un nettoyeur générique:
Merci beaucoup Kevin, ça a l'air d'être bien le RAII, même si ça multiplie les classes (ce que j'aime pas trop).Par contre, si ça a l'air utile pour les objets dont la durée de vie est locale à une fonction, ça n'a pas l'air si approprié à mon cas : de multiples appels de fonction dans un constructeur. Ceci dit, je retiens cette technique d'encapsulation des ressources.
template <class T> Cleanup {
private:
T *m_p;
void (T::*m_pCleanup)();
public:
Cleanup (T *p, void (T::*pCleanup)()) : m_p(p), m_pCleanup(pCleanup) {}
~Cleanup() {m_p->m_pCleanup();}
}
// Create the button texture (transparent) and set it as render target
m_Texture = SDL_CreateTexture(Game::get()->renderer(), px, SDL_TEXTUREACCESS_TARGET, width, height);
if (m_Texture == nullptr) throw Exception(ERROR_SDL_STR);
Cleanup<MyClass> c(this, &MyClass::cleanup);
if (SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND) != 0) throw Exception(ERROR_SDL_STR);
if (SDL_SetRenderDrawColor(Game::get()->renderer(), 0, 0, 0, 0) != 0) throw Exception(ERROR_SDL_STR);
if (SDL_RenderClear(Game::get()->renderer()) != 0) throw Exception(ERROR_SDL_STR);
if (SDL_SetRenderTarget(Game::get()->renderer(), m_Texture) != 0) throw Exception(ERROR_SDL_STR);
Lionel Debroux (./21) :inux utilise la forme if (truc) machin;
Les structures de contrôle sans accolades sont connues pour avoir causé, par exemple, un bug de sécurité grave dans le kernel Linux il y a des années.
Parce que le kernel L
our être peu lisible. En écrivant if (truc) machin; qui est connue p
tu n'as pas ce problème.