| 214 | |
| 215 | template<typename T, typename std::enable_if<std::is_signed<T>::value, bool>::type=true> |
| 216 | bool strToInt(const std::string& str, T &num, std::string* err = nullptr) |
| 217 | { |
| 218 | long long tmp; |
| 219 | try { |
| 220 | std::size_t idx = 0; |
| 221 | tmp = std::stoll(str, &idx); |
| 222 | if (idx != str.size()) { |
| 223 | if (err) |
| 224 | *err = "not an integer (pos)"; |
| 225 | return false; |
| 226 | } |
| 227 | } catch (const std::out_of_range&) { |
| 228 | if (err) |
| 229 | *err = "out of range (stoll)"; |
| 230 | return false; |
| 231 | } catch (const std::invalid_argument &) { |
| 232 | if (err) |
| 233 | *err = "not an integer (invalid_argument)"; |
| 234 | return false; |
| 235 | } |
| 236 | if (str.front() == '-' && std::numeric_limits<T>::min() == 0) { |
| 237 | if (err) |
| 238 | *err = "needs to be positive"; |
| 239 | return false; |
| 240 | } |
| 241 | if (str.front() != '+' && str.front() != '-' && isdigit(str.front()) == 0) { |
| 242 | if (err) |
| 243 | *err = "not an integer"; |
| 244 | return false; |
| 245 | } |
| 246 | if (str.size() > 1 && str.front() == '0') { |
| 247 | if (err) |
| 248 | *err = "not an integer"; |
| 249 | return false; |
| 250 | } |
| 251 | if (tmp < std::numeric_limits<T>::min() || tmp > std::numeric_limits<T>::max()) { |
| 252 | if (err) |
| 253 | *err = "out of range (limits)"; |
| 254 | return false; |
| 255 | } |
| 256 | num = static_cast<T>(tmp); |
| 257 | return true; |
| 258 | } |
| 259 | |
| 260 | template<typename T, typename std::enable_if<std::is_unsigned<T>::value, bool>::type=true> |
| 261 | bool strToInt(const std::string& str, T &num, std::string* err = nullptr) |