Evaluate expression at compile time

I know that this was given a lot, but only for C / C ++ and Java. The question is related to the benefits of using constant expressions:

When I call a static function with only constants as arguments, is there a way to tell the compiler that it should evaluate the call already at compile time and replace the call with the result?

Example:

const double pi = Math.PI; //works as Math.PI is a constant const double spi = Math.Sin(Math.PI); //compiler error, because expression must be constant 

Are there any directives (better: Attributes) to directly tell the compiler that a static method such as Math.Sin () does not modify or read any data inside, so that it is technically possible to evaluate the call at compile time?

Oh, and please don’t answer like "just do const double spi = 0 " :), because my example is just a simplified version of the problem I have: Improving maintainability of the code while maintaining maximum performance.

Thanks for any help - this is really appreciated!

+5
source share
2 answers

For numerical constants, I see two options:

Option one: use static readonly (calculated once at startup):

 class MyCalc { private static readonly double spi = Math.Sin(Math.PI); private static readonly double pi = Math.Sin(Math.PI); public void Execute() { // .. whatever } } 

Option two: do the calculations with your pocket calculator and copy these constants:

 class MyCalc { // Math.Sin(Math.Pi) private const double spi = 0; // Math.Pi private const double pi = 3.141592653589793; public void Execute() { // .. whatever } } 

I'm not sure if the compiler can fully optimize the option one in the calculation, but it should be the most readable and supported way.

If you are looking for as much compilation time as possible, things get more complicated. In C ++, you have templates. I find them cumbersome to write, but people get amazing things done with it. It seems easier to compile time functions with , but I have not tried them yet. D have CTFE , which is really powerful. But D is a niche, and I would not write serious code in it. I do not know other languages ​​with a significant explicit assessment of precompilation, but I am sure that there are some.

Compilers are no longer smart today. Most likely, the compiler can see the ability to integrate the optimization of a function call without a hint. With DotNet 4.5, we have an AggressiveInlining -attribute so that we can force the compiler in the right direction. C / C ++ have something similar, and there were problems. General recommendations on my part are to avoid inline until you know exactly what you are doing.

If you really do not want to go this route with C #, the best option in my eyes would be to write your functionality in C ++ using the specified functions, write an easy-to-use C-interface and call it PInvoke . But do yourself a favor and try on if it is really worth it. Never forget two optimization rules:

  • Not
  • So far (only experts)
+3
source

There is a [Pure] attribute for methods that do not have side effects. However, this is used only for code analysis, and not for the compiler (for now). However, this may change in the future.

JetBrains ReSharper provides a similar [Pure] attribute for the same purpose (code analysis).

So, for now, you need a workaround, as a value previously calculated by you, best with a comment for someone else, to find out the source of the value:

 const double spi = 0.0; // Math.Sin(Math.PI) 

or

 static readonly double spi = Math.Sin(Math.PI); 

which, of course, calculates a value for runtime that you don't want.

+1
source

Source: https://habr.com/ru/post/1235178/


All Articles