, 1 min read
C++20: consteval and constexpr functions
Optimizing compilers seek try to push as much of the computation as possible at compile time. In modern C++, you can declare a function as ‘constexpr’, meaning that you state explicitly that the function may be executed at compile time.
The constexpr qualifier is not magical. There may not be any practical difference in practice between an inline function and a constexpr function, as in this example:
inline int f(int x) {
return x+1;
}
constexpr int fc(int x) {
return x+1;
}
In both cases, the compiler may compute the result at compile time.
The fast_float C++ library allows you to parsing strings to floating-point numbers at compile time if your compiler supports C++20. Thus you can write the following function which returns either the parsed floating-point value or the number -1.0 in case of error:
constexpr double parse(std::string_view input) {
double result;
auto answer = fast_float::from_chars(input.data(),
input.data()+input.size(), result);
if(answer.ec != std::errc()) { return -1.0; }
return result;
}
So what happens if you put parse("3.1416") in your code? Unfortunately, even at the highest optimization levels, you cannot be certain that the function will be computed at compile time.
Thankfully, C++20 has an another attribute ‘consteval’ which ensures that the function is evaluated at compile time:
consteval double parse(std::string_view input) {
double result;
auto answer = fast_float::from_chars(input.data(),
input.data()+input.size(), result);
if(answer.ec != std::errc()) { return -1.0; }
return result;
}
What happens if the parameter of the function cannot be determined at compile time? There should be a compilation error.
With the consteval qualifier, the following two functions should be practically equivalent:
double f1() {
return parse("3.1416");
}
double f2() {
return 3.1416;
}
You can try it out with fast_float if you’d like.