2

In C++20 we now have constinit. constexpr and consteval.

I can now guarantee that a static variable is initialized by the result of a constexpr or consteval function by using constinit. OK

I also can guarantee that a stack variable is initialized with the result of a consteval function executed in compile time.

But how can I force to run a constexpr function to calculate a result in compile time to init a variable on stack?

// Lets assume that we have a much more complex function so that the compiler will not
// always decide to compile time evaluation automatically 
constexpr int func( int i )
{
    return i+2;
}

int main()
{
     ??? int i = func(8);
     ...
     i = 9;
}

If we use constexpr the variable is implicitly const and constinit is not allowed here. Any chance to initialize this var with the compile time evaluated result of a constexpr function without making it const? I am simply wondering why constinit is limited to static variables. For my it makes not much sense.

Klaus
  • 24,205
  • 7
  • 58
  • 113

2 Answers2

4

I think it is better to use consteval function, but if you cannot change it, you can simply use a temporary variable which will surely optimize later:

constexpr int func( int i )
{
    return i+2;
}

int main()
{
     constexpr int i1 = func(8);
     auto i2 = i1;
     i2 = 9;
}

Although you may not like this method, I think it works without any problem....

You can also use something like this(Based on StoryTeller idea):

template<typename T> constexpr std::remove_const_t<T> const_eval(T&& res) { return res; }

which support returning references from method too.

Afshin
  • 8,839
  • 1
  • 18
  • 53
4

I am simply wondering why constinit is limited to static variables. For my[sic] it makes not much sense.

Constant initialization and dynamic initialization are concepts that apply only to objects with static storage duration. The constinit specifier merely means to enforce our expectation that a variable will undergo the former, rather than the latter. It's not an optimization tool, but a way to codify how our code is meant to behave. Without it, dynamic initialization can happen silently, and as any C++ programmer who has been around the block can tell you, that also means the static initialization order fiasco can occur.

With constinit, we either get the expected behavior or a diagnostic. It doesn't apply to automatic variables because they don't suffer from the same problem static variables do.

But if you want to ensure i is initialized by something that can be constant evaluated, then it's not too hard to accomplish.

template<auto result> consteval auto const_eval() { return result; }

int main()
{
     int i = const_eval<func(8)>();
     i = 9;
}

If func(8) cannot be constant evaluated, it's a hard error. Will a compiler optimize it to a load of a constant value? Very likely. Compilers are good at that sort of thing.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • OK, only a workaround possible... feels like a language bug to me! – Klaus Jan 10 '22 at 11:33
  • 3
    @Klaus: The language provides few ways of specifying optimizations in general: the idea is that you should trust the implementation to pick what constant-folding to do just like you trust it to inline when appropriate. – Davis Herring Jan 10 '22 at 14:29
  • @DavisHerring: My current use case and the reason why I ask is a small embedded system (AVR) with very low memory ( ram/flash ). "Trust" is not enough, it needs to have a lot of "force" to get working code! If on a PC some lines are not optimized, it is not a problem, but if interrupt handlers on a uC will not really optimized, it is a show stopper! However, it feels like a design bug that `constinit` can not be used for stack vars. – Klaus Jan 11 '22 at 08:07
  • @Klaus - You keep insisted on a "design bug" while neglecting it's doing exactly what it was designed *for*. Can it be **expanded** to stack variables? Maybe. But that's something that was not part of the goal. If you are on a specific platform, you'd be better off using platform specific methods to get you that constant in a way you'll be *sure*. – StoryTeller - Unslander Monica Jan 11 '22 at 08:58
  • @StoryTeller-UnslanderMonica: ""design bug" while neglecting it's doing exactly what it was designed for" Thats why I call it a design bug and not an implementation bug. "If you are on a specific platform, you'd be better off using platform specific methods " I want to reuse non platform specific code. If I follow at the end to guarantee all my self, I can write a code generator which puts all I need somewhere in flash and the rest is assembler... hey, we all want to use C++ because it is a good common language from uC to mainframe. If `constinit` can be used, it is a bit more perfect... – Klaus Jan 11 '22 at 09:27