I've rolled out my own assertions that always fire in release mode too, based on this article:
This is the GIST of it, with me not providing the actual implementation (of AbstractAsserter, which is based on the article), but you get the idea:
#include <iostream>
struct AbstractAsserter
{
    virtual void doAssert(const char* expr, const char* file, int line, const char* function) const
    {
        std::cout << "Asserting now at " << expr << ", " << file << ", " << line << ", " << function << std::endl;
    }
};
struct Local
{
  const char* function_;
  const char* expr_;
  const char* file_;
  int line_;
  Local( const char* f, const char* ex, const char* file, int line )
  : function_( f ), expr_( ex ), file_( file ), line_( line )
  { }
  Local operator << ( const AbstractAsserter& impl )
  {
    impl.doAssert( expr_, file_, line_, function_ );
    return *this;
  }
};
// More to be added as required...
#if defined( __GNUC__ )
# define WE_FUNCTION __PRETTY_FUNCTION__
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
# define WE_FUNCTION __func__
#else
# define WE_FUNCTION "null_func()"
#endif
#define WE_ASSERT( expr )\
  if( expr );\
  else Local( WE_FUNCTION, #expr, __FILE__, __LINE__ )\
    << AbstractAsserter();
int main() {
    WE_ASSERT(!"bad BAD BOY!");
    return 0;
}
With this structure, your implementation may also do some critical saving of state etc (if you deem your program state trustworthy...debatable).