What are the advantages of using consteval instead of constexpr function?
Asked Answered
S

1

9

I know the difference in requirements, I am mostly interested in what benefits from code quality it brings.

Few things I can think of:

  • reader can just read the function signature and know that function is evaluated at compile time
  • compiler may emit less code since consteval fns are never used at runtime(this is speculative, I have no real data on this)
  • no need to have variables to force ctfe, example at the end

note: if code quality is too vague I understand some people might want to close this question, for me code quality is not really that vague term, but...

example where constexpr failure is delayed to runtime:

constexpr int div_cx(int a, int b)
{ 
  assert(b!=0);
  return a/b;
}
    
int main()
{
    static constexpr int result = div_cx(5,0); // compile time error, div by 0
    std::cout << result; 
    std::cout << div_cx(5,0) ; // runtime error :( 
}
Sphalerite answered 8/11, 2020 at 18:24 Comment(3)
Are you asking for the motivation for consteval? I seem to recall the specific reason being performance and reflection. I recall there being a performance cost to keeping constexpr functions available for runtime. I also recall that some kinds of reflection types can only exist at compile time or should only exist at compile time (for security reasons). consteval would provide a mechanism to enforce this.Euthanasia
@Euthanasia not interested in design, more what the average dev who does not care about language lawyer stuff can get out of it... Something like hyoptheical effective consteval book by scott meyers :)Sphalerite
I don't think the average dev is going to benefit from consteval yet. This feature is just one part of the groundwork being laid for static reflection in C++, and it will be very useful then. For now, I don't think there's much practical use (except as you've kind of pointed out, when you really care that no assembly is generated for some function).Elson
B
22

In order to have meaningful, significant static reflection (reflection at compile time), you need a way to execute code at compile time. The initial static reflection TS proposal used traditional template metaprogramming techniques, because those were the only effective tools for executing code at compile-time at all.

However, as constexpr code gained more features, it became increasingly more feasible to do compile-time static reflection through constexpr functions. One problem with such ideas is that static reflection values cannot be allowed to leak out into non-compile-time code.

We need to be able to write code that must only be executed at compile-time. It's easy enough to do that for small bits of code in the middle of a function; the runtime version of that code simply won't contain the reflection parts, only the results of them.

But what if you want to write a function that takes a reflection value and returns a reflection value? Or a list of reflection values?

That function cannot be constexpr, because a constexpr function must be able to be executed at runtime. You are allowed to do things like get pointers to constexpr functions and call them in ways that the compiler can't trace, thus forcing it to execute at runtime.

A function which takes a reflection value can't do that. It must execute only at compile-time. So constexpr is inappropriate for such functions.

Enter consteval: a function which is "required" to execute only at compile time. There are specific rules in place that make it impossible for pointers to such functions to leak out into runtime code and so forth.

As such, consteval doesn't have much purpose at the moment. It gets used in a few places like source_location::current(), which fundamentally makes no sense to execute at runtime. But ultimately, the feature is a necessary building-block for further compile-time programming tools that don't exist yet.

This was laid down in the paper that originally proposed this feature:

The impetus for the present paper, however, is the work being done by SG7 in the realm of compile-time reflection. There is now general agreement that future language support for reflection should use constexpr functions, but since "reflection functions" typically have to be evaluated at compile time, they will in fact likely be immediate functions.

Banns answered 8/11, 2020 at 19:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.