I think cout is only allowed to run at runtime but the following code proves otherwise. Or am I not understanding something deeper? I only expected it to print the message once, but it printed twice. Why is that?
import std;
constexpr void logError(const std::string& error);
constexpr int sqrt(int x)
{
if (x < 0)
{
logError("Oh no, this can't be real...");
return -1;
}
else
{
int result{ 1 };
while (result * result <= x) ++result;
return result - 1;
}
}
int c = sqrt(-1);
int main()
{
sqrt(-1);
}
constexpr void logError(const std::string& error)
{
if (!std::is_constant_evaluated())
std::cout << error << std::endl;
}
I think this code int c = sqrt(-1); calls logError, but it is not allowed, isn't it?
You're right about
std::cout. You just misunderstand howconstexprrelates to compile-time evaluation.constexprdoesn't mean thatlogErroris run at compile-time. It merely means that the function can possibly run at compile-time, if needed.... is not a case where a constant expression is required to initialize
c, sosqrt(-1)as run at run-time. See also When does a constexpr function get evaluated at compile time?Furthermore, it would be safe to run
logErrorat compile-time because the check forstd::is_constant_evaluated()ensures thatstd::cout <<isn't done within a constant expression. See C++20 constexpr std::copy optimizations for run-time for an example of how it's typically used.Further notes
It's not a good idea to split
constexprfunctions into declaration and definition like you've done. Aconstexprfunction can only be used within a a constant expression once it's been defined. See also Use of constexpr function before definition fails