Can this if-statement be replaced with a #if ....
macro?
Possibly without having to include (too many) extra headers.
#include <cstdint>
#include <string>
///Parse a string to obtain a fixed width type
inline uint64_t stou64(const std::string& in) {
if (sizeof(unsigned long) == sizeof(uint64_t)) {
return std::stoul(in);
} else {
return std::stoull(in);
}
}
CodePudding user response:
You don't need pre-processor macro for this. The function is well-defined regardless of the size, and the compiler is smart enough to optimise the unused branch away completely.
If you want to be sure that the unused branch is removed even with optimisation disabled, you can use if constexpr. Simply add constexpr
after if in your example.
If you don't need to support currently active locale, then consider using std::from_chars
instead.
CodePudding user response:
No, your if
statement is different because both the if and the else path are compiled and must be valid expressions, even if the compiler then optimizes the code to only the path taken. In an #if
macro only the part that remains is seen by the compiler. The eliminated part doesn't have to be sensical for the given argument.
Since this can be an issue with templates the constexpr if syntax was added in c 17.
#include <cstdint>
#include <string>
///Parse a string to obtain a fixed width type
inline uint64_t stou64(const std::string& in) {
if constexpr (sizeof(unsigned long) == sizeof(uint64_t)) {
return std::stoul(in);
} else {
return std::stoull(in);
}
}
Note: In this specific example it doesn't matter. But why not get used to if constexpr
anyway?
CodePudding user response:
I prefer this approach (before C 17 std::from_chars
):
template<typename T>
T string_to(const std::string& in);
template<>
int string_to<int>(const std::string& in) {
return std::stoi(in);
}
template<>
unsigned string_to<unsigned>(const std::string& in) {
return std::stol(in);
}
template<>
long string_to<long>(const std::string& in) {
return std::stol(in);
}
template<>
long long string_to<long long>(const std::string& in) {
return std::stoll(in);
}
template<>
unsigned long string_to<unsigned long>(const std::string& in) {
return std::stoul(in);
}
template<>
unsigned long long string_to<unsigned long long>(const std::string& in) {
return std::stoull(in);
}
inline uint64_t stou64(const std::string& in) {
return string_to<uint64_t>(in);
}