The compiler is pretty unlikely to manage to throw out the conversion no matter what. Exceptions are just the icing on the cake. If you want to optimize this, you'll have to write your own parser to recognize the format for a float. Use regexps or manually parse, since the pattern is simple:
if ( s.empty() ) return false;
string::const_iterator si = s.begin();
if ( *si == '+' || * si == '-' ) ++ si;
if ( si == s.end() ) return false;
while ( '0' <= *si && *si <= '9' && si != s.end() ) ++ si;
if ( si == s.end() ) return true;
if ( * si == '.' ) ++ si;
if ( ( * si == 'e' || * si == 'E' )
&& si - s.begin() <= 1 + (s[0] == '+') + (s[0] == '-') ) return false;
if ( si == s.end() ) return si - s.begin() > 1 + (s[0] == '+') + (s[0] == '-');
while ( '0' <= *si && *si <= '9' && si != s.end() ) ++ si;
if ( si == s.end() ) return true;
if ( * si == 'e' || * si == 'E' ) {
++ si;
if ( si == s.end() ) return false;
if ( * si == '-' || * si == '+' ) ++ si;
if ( si == s.end() ) return false;
while ( '0' <= *si && *si <= '9' && si != s.end() ) ++ si;
}
return si == s.end();
Not tested… I'll let you run through all the possible format combinations ;v)
Edit: Also, note that this is totally incompatible with localization. You have absolutely no hope of internationally checking without converting.
Edit 2: Oops, I thought someone else already suggested this. boost::lexical_cast
is actually deceptively simple. To at least avoid throwing+catching the exception, you can reimplement it somewhat:
istringstream ss( s );
double d;
ss >> d >> ws; // ws discards whitespace
return ss && ss.eof(); // omit ws and eof if you know no trailing spaces
This code, on the other hand, has been tested ;v)