base: Use if constexpr to simplify the templates in __to_number.

The c++-17 feature "if constexpr" allows you to put code inside a normal
if which would normally have to be separated out using templates. The
condition of the if must be compile time evaluated, and the not-taken
path is discarded by the compiler.

Change-Id: I026381b2dbb140ef7f1b5cb23803782683ec419c
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/48503
Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
Maintainer: Daniel Carvalho <odanrc@yahoo.com.br>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Gabe Black
2021-07-23 21:23:08 -07:00
parent faae3f0be9
commit 0f2fb7bbb4

View File

@@ -110,27 +110,9 @@ tokenize(std::vector<std::string> &vector, const std::string &s,
* @name String to number helper functions for signed and unsigned
* integeral type, as well as enums and floating-point types.
*/
template <class T>
typename std::enable_if_t<std::is_integral<T>::value &&
std::is_signed<T>::value, T>
__to_number(const std::string &value)
{
// Cannot parse scientific numbers
if (value.find('e') != std::string::npos) {
throw std::invalid_argument("Cannot convert scientific to integral");
}
// start big and narrow it down if needed, determine the base dynamically
long long r = std::stoll(value, nullptr, 0);
if (r < std::numeric_limits<T>::lowest()
|| r > std::numeric_limits<T>::max()) {
throw std::out_of_range("Out of range");
}
return static_cast<T>(r);
}
template <class T>
typename std::enable_if_t<std::is_integral<T>::value &&
!std::is_signed<T>::value, T>
typename std::enable_if_t<std::is_integral_v<T>, T>
__to_number(const std::string &value)
{
// Cannot parse scientific numbers
@@ -138,21 +120,26 @@ __to_number(const std::string &value)
throw std::invalid_argument("Cannot convert scientific to integral");
}
// start big and narrow it down if needed, determine the base dynamically
unsigned long long r = std::stoull(value, nullptr, 0);
if (r > std::numeric_limits<T>::max())
throw std::out_of_range("Out of range");
return static_cast<T>(r);
if constexpr (std::is_signed_v<T>) {
long long r = std::stoll(value, nullptr, 0);
if (r < std::numeric_limits<T>::lowest()
|| r > std::numeric_limits<T>::max()) {
throw std::out_of_range("Out of range");
}
return static_cast<T>(r);
} else {
unsigned long long r = std::stoull(value, nullptr, 0);
if (r > std::numeric_limits<T>::max())
throw std::out_of_range("Out of range");
return static_cast<T>(r);
}
}
template <class T>
typename std::enable_if_t<std::is_enum<T>::value, T>
__to_number(const std::string &value)
{
// Cannot parse scientific numbers
if (value.find('e') != std::string::npos) {
throw std::invalid_argument("Cannot convert scientific to integral");
}
auto r = __to_number<typename std::underlying_type<T>::type>(value);
auto r = __to_number<typename std::underlying_type_t<T>>(value);
return static_cast<T>(r);
}