I'm trying to convert an std::string to an int with a default value if the conversion fails. C's atoi() is way too forgiving and I've found that boost::lexical_cast is quite slow in the case where the cast fails.  I imagine it's because an exception is raised. I don't have C++11, so stoi() is out.The Delphi function StrToIntDef is the ideal, and it's also available in C-Builder (where I'm working currently).  But I want something more portable that works with std::string. I've created the following function, which uses atoi() but first tests for error conditions. It also allows for leading and trailing spaces, which are harmless in my situation.int stringtoIntDef(const std::string & sValue, const int & DefaultValue) {// convert a std::string to integer with a default value returned// in the case where the string doesn't represent a valid integer // - accepts leading or trailing spaces as valid   bool hasDigits = false;   bool TrailingSpace = false;   for (std::string::size_type k = 0; k < sValue.size(); ++k) {      if ((sValue[k] == ' ') || (sValue[k] == '\t')) {         TrailingSpace = hasDigits;      } else if ((sValue[k] == '0') || (sValue[k] == '1') || (sValue[k] == '2') || (sValue[k] == '3') ||                  (sValue[k] == '4') || (sValue[k] == '5') || (sValue[k] == '6') || (sValue[k] == '7') ||                  (sValue[k] == '8') || (sValue[k] == '9')) {         if (TrailingSpace) {            return DefaultValue;         } else {            hasDigits = true;         }      } else if ((sValue[k] == '-') && !hasDigits) {         hasDigits = true; // this protects against --      } else {         return DefaultValue;      }   }   return atoi(sValue.c_str());}In my testing, I've compared it against StrToIntDef and it is just as fast, but lexical_cast is much slower in the case where the default is returned. For 1000 iterations, lexical_cast took 5 seconds while the other 2 weren't measurable.For my lexical_cast function, I've used this:try {    return boost::lexical_cast<int>(sValue);}catch (boost::bad_lexical_cast &) {    return DefaultValue;}Are there any gotchas I might have missed here?
Converting std::string to int without Boost
c++;converting;boost
This is a follow up to your second follow up. I just have a few comments, and you have two bugs.stringtoIntDef is a strange name. In particular, why are Int and Def capitalized but not To? I would go either full camelCase, or I would use the standard library convention of under_scores.You never delete[] s which means you have a memory leak.I actually meant in my comment that you could check the end pointer from strtol to see if all that follows is either nothing or 0. I should have been more specific. An example of this is below.If cstdlib was included (as it should be) rather than stdlib.h, then strtol needs to be std::strtol. The cheader-style headers guarantee declarations in the std namespace, but they do not guarantee declarations in the global namespace. (Every C++ implementation I've ever seen does both, but they not required to do the global namespace.)Define variables as late as possible. In other words, declare result when you're defining it to be strtol's return value.If you don't want a variable to change after its initial value, make it const. This keeps you from accidentally changing the value, and it makes your intentions more clear to anyone who inherits the code.You must provide a base of 10 to strtol, not 0. 0 is the default and it means to try to parse a number as base 10 unless it's prefixed with either 0x (for hex) or 0 (for octal). Assuming you want just decimal, it must be 10.If you do want the default behavior, don't put the 0. Just let it default to 0. Default behavior and and an empty default value have a nice symmetry to them, and it allows for future change of what the default sentinel value is without breaking consuming code.Since it's never modified anywhere, str should be passed by constant reference, not reference.If you were going to copy the string (don't! memory allocation is both unnecessary here and is very slow compared to the rest of the operations we're using), I would take the string by value and modify the parameter. That would allow for moving in C++11, and it would conveniently handle the memory allocation for you. The (potentially major) downside to this approach would be that obviously invalid strings could cause a rather large copy. Imagine if you passed a string of pure whitespace. All that whitespace would be copied for nothing other than to get immediately removed.We both missed the case of an empty string. strtol output can be used to detect it (begp == endp), but neither of us checked for that :).I still disagree with your decision to hide the ability to check for errors, but if that's the route you want to take, I would do something like this:int string_to_int(const std::string& str, const int& DefaultValue) {    errno = 0;    const char* str_beg = str.c_str();    const char* str_end = str_beg + str.size();    char* p = NULL;    const int result = std::strtol(str.c_str(), &p, 10);    if (p == str_beg) { return DefaultValue; }    for (; p != str_end && std::isspace(*p); ++p) { /* eat trailing spaces */}    if (p != str_end || errno != 0) {        return DefaultValue;    }    return result;}(This could probably be optimized quite a bit, but it would likely be compiler/system specific, and it would be tedious.)