Home > front end >  Limiting the scope of a temporary variable
Limiting the scope of a temporary variable

Time:09-28

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.

  1. Storage is first reserved on the stack for x_lo and x_hi.
  2. The quotient_and_remainder is then pushed temporarily onto the stack.
  3. The quotient_and_remainder is used to calculate values which are written into x_lo and x_hi.
  4. Having done its duty, the quotient_and_remainder is popped off the stack.

At the high programming level, one desires the following.

  1. The compiler enforces that x_lo and x_hi remain constant.
  2. 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);

Demo

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.

  • Related