Thumbs up on assertions.
All dev environments I've used can be configured to automatically break on assert, so in my experience no additional code is required there.
The only downside with asserts are that they're obviously of no use unless they go off on the developer's computer, in a debug build.
What I'll propose here might seem like overkill to some. But it has been invaluable for me in the past dealing with errors on other user's computers. I figured I'd suggest it and let you folks decide if it's useful.
My preference is to define an ASSERT macro which asserts and logs
once.
In SFML's case, the error would be sent to the sf::err stream instead of a logfile. But the discussion below applies regardless, since I imagine many SFML applications redirect the SFML error stream to a log file.
With logging, you can diagnose the logic error on a remote user's computer in release mode by examining the log file. But it's important to only log once, so that if an assert goes off in a per-frame loop (or worse), you don't create a gazigabyte logfile with the error spammed over and over.
My ASSERT macro looks something like this:
#define ASSERT(x) \
do { if (!(x)) { if ( LogAssert( __FILE__, __LINE__ ) ) assert(x); } } while( 0 );
Here's a good discussion about why all that extra do/if/while stuff is needed:
http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/My LogAssert function is pretty complicated, but here's a simplified version which captures the essence. It uses a data member to track previous asserts as follows:
// A set of (file name, line number) of previously triggered asserts
std::set< std::pair<std::string, int> > m_setPreviousAssert;
bool LogAssert( const char* const i_szFile, int i_nLine )
{
std::pair< std::string, int > pairAssertInfo( i_szFile, i_nLine );
if ( m_setPreviousAssert.count(pairAssertInfo) == 0 )
{
// First trigger of this assert
// Track and log.
m_setPreviousAssert.insert(pairAssertInfo);
std::stringstream ssMsg;
ssMsg << "[ASSERT] " << i_szFile << ":" << i_nLine;
Log( ssMsg.str() );
return true;
}
return false;
}
This achieves logging all asserts once, and provides a file and line number in the log file for the assert.