Without resorting to the heap, I would like a temporary variable to pass out of scope, freeing its storage on the stack. However, I can think of no neat way to achieve the desired effect in a case like this:
#include <cstdlib>
#include <iostream>
int main()
{
const int numerator {14}, denominator {3};
// ...
// The desired scope begins here.
const std::div_t quotient_and_remainder {std::div(numerator, denominator)};
const int x_lo {
quotient_and_remainder.quot
};
const int x_hi {
quotient_and_remainder.quot (quotient_and_remainder.rem ? 1 : 0)
};
// The desired scope ends here.
// The quotient_and_remainder should pass out of scope.
// ...
std::cout
<< "The quotient " << numerator << "/" << denominator
<< " is at least " << x_lo
<< " and is not more than " << x_hi << "." << "\n";
return 0;
}
At the low machine level, one desires the following.
- Storage is first reserved on the stack for
x_lo
andx_hi
. - The
quotient_and_remainder
is then pushed temporarily onto the stack. - The
quotient_and_remainder
is used to calculate values which are written intox_lo
andx_hi
. - Having done its duty, the
quotient_and_remainder
is popped off the stack.
At the high programming level, one desires the following.
- The compiler enforces that
x_lo
andx_hi
remain constant. - The name
quotient_and_remainder
does not clutter the function's entire local namespace.
At both levels, one would like to avoid wasting memory and runtime. (To waste compilation time is okay.)
In my actual program—which is too long to post here—the values of numerator
and denominator
are unknown at compile time, so constexpr
cannot be used.
Ordinarily, I can think of various sound ways to achieve such effects using, for example, extra braces or maybe an anonymous lambda; but this time, I'm stumped.
(One should prefer to solve the problem without anti-idiomatic shenanigans like const_cast
. However, if shenanigans were confined to a small part of the program to avert maintainabilty problems, then shenanigans might be acceptable if there existed no better choice.)
CodePudding user response:
In C 17, you can use a function and a structured binding declaration:
auto x_lo_x_hi = [](int numerator, int denominator) {
std::div_t quotient_and_remainder {std::div(numerator, denominator)};
return std::pair{
quotient_and_remainder.quot,
quotient_and_remainder.quot (quotient_and_remainder.rem ? 1 : 0)
};
};
const auto [x_lo, x_hi] = x_lo_x_hi(numerator, denominator);
x_lo_x_hi
doesn't have to be a local lambda. It could be some function declared elsewhere or it could even be an IIFE (an anonymous lambda that you call immediately on the same line).
That said, this only serves to remove the name quotient_and_remainder
from the local scope. Like MSalters said in a comment, any decent compiler will optimize that variable away in your original code. And even if it didn't, removing one variable from the stack will not improve the runtime, and if you have stack memory problems, the actual issue is somewhere else.