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.
CodePudding user response:
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> constexpr 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.
CodePudding user response:
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.