Question: Confusion regarding converting recursion to iteration using stack

I have a big confusion on what is meant by the general method of converting recursive functions (tail and non tail) to iterative ones using stack. I made this simple example to illustrate the point:
int sigma1(int n) {
  if(n == 0) 
    return 0;
  else 
    return n + sigma1(n-1);
}

which of the following versions reflects the method correctly:
Version 1
int sigma1_iter(int n) {
  stack* s = create_stack(n);
  push(s, n);
  int res = 0;
  while(!is_empty(s)) {
    int elm = pop(s);
    if(elm == 0)
      return res;
    else {
      res += n;
      push(s, n-1);
    }
  }
}


Version 2
int sigma1_iter(int n) {
  stack* s = create_stack(n);
  push(s, n);
  int res = 0;
  while(!is_empty(s)) {
    if (n > 0) {
      n--;
      push(s, n);
    }
    else {
      int elm = pop(s);
      if(elm == 0)
        return res;
      else {
        res += n;
    }
  }
}

Also, in case of the tail recursive version of sigma with an accumulator:
int sigma2(int n, int res) {
  if (n == 0) 
    return res;
  else
    return sigma2(n-1, n+res);
}

How would one convert it? I am thinking of creating a second stack for res, but how that might work?


Answer:
Be sure to post a minimal, reproducible example when you ask a question. That helps everyone understand the question and generate and test potential answers.
If you had created such an example, it would be evident that version 1 of your iterative solution never returns and version 2 always returns 0 making neither a good candidate for correctness.
Recursion can be challenging, but I think we can walk through a general method for converting a recursive function to an iterative function for this example.
Let's look at the recursive implementation for sigma1,
int sigma1(int n) {
    if (n == 0)
        return 0;
    else
        return n + sigma1(n - 1);
}

Under the hood, calling this function generates a new stack frame for each recursive invocation (assuming the compiler doesn't optimize it away). Each of these call frames will have the value of the argument n for that frame which will decrease by one at each level of recursion. We can think about the iterative version, in the same way, storing the value of n on our explicit std::stack<int> instead of it being handled automagically by the call stack.
When the recursion terminates and the call frames unwind, the local value of n is added to the result of the previous call creating a new result to be returned. In the same way, we can pop values from the explicit std::stack<int> and add them to the running total in the iterative version.
The function would look something like this,
int sigma1_stack(int n) {
    std::stack<int> stack;
    for (int i = n; i > 0; --i)
        stack.push(i);

    int res{};
    while (not stack.empty()) {
        res += stack.top();
        stack.pop();
    }

    return res;
}

Now, in this particular scenario, you can simplify the two loops into a single iterative loop without a stack. This, of course, will not always be the case.
int sigma1_iter(int n) {
    int res{};
    for (int i = n; i > 0; --i)
        res += i;
    return res;
}

I took the code you posted and changed it to compile using a std::stack<int> since you did not post a complete example. I also added a correct version of iteration for both sigma1 and sigma2 and the corresponding output. Hope this is helpful.
Sample Code
#include <iostream>
#include <stack>

using std::cout, std::endl;

int sigma1(int n) {
    if (n == 0)
        return 0;
    else
        return n + sigma1(n - 1);
}

int sigma1_iter_v1(int n) {
    std::stack<int> stack;
    stack.push(n);

    int res = 0;
    while (not stack.empty()) {
        int elm = stack.top();
        stack.pop();
        if (elm == 0)
            return res;
        else {
            res += n;
            stack.push(n - 1);
        }
    }

    return res;
}

int sigma1_iter_v2(int n) {
    std::stack<int> stack;
    stack.push(n);

    int res = 0;
    while (not stack.empty()) {
        if (n > 0) {
            n--;
            stack.push(n);
        } else {
            int elm = stack.top();
            stack.pop();
            if(elm == 0)
                return res;
            else {
                res += n;
            }
        }
    }

    return res;
}

int sigma1_iter(int n) {
    int res{};
    for (int i = n; i > 0; --i)
        res += i;
    return res;
}

int sigma1_stack(int n) {
    std::stack<int> stack;
    for (int i = n; i > 0; --i)
        stack.push(i);

    int res{};
    while (not stack.empty()) {
        res += stack.top();
        stack.pop();
    }

    return res;
}

int sigma2(int n, int res = 0) {
    if (n == 0)
        return res;
    else
        return sigma2(n - 1, n + res);
}

int sigma2_iter(int n) {
    int res{};
    for (int i = n; i > 0; --i)
        res += i;
    return res;
}

int main(int argc, const char *argv[]) {
    cout << "sigma1         : " << sigma1(20) << endl;
    cout << "sigma1_iter   : " << sigma1_iter(20) << endl;
    cout << "sigma1_stack  : " << sigma1_stack(20) << endl;
    // This never returns
    // cout << "sigma1_iter_v1 : " << sigma1_iter_v1(20) << endl;
    cout << "sigma1_iter_v1 : " << "never returns" << endl;
    cout << "sigma1_iter_v2 : " << sigma1_iter_v2(20) << endl;

    cout << endl;
    cout << "sigma2         : " << sigma2(20) << endl;
    cout << "sigma2_iter    : " << sigma2_iter(20) << endl;
    return 0;
}

Output
sigma1         : 210
sigma1_iter    : 210
sigma1_stack   : 210
sigma1_iter_v1 : never returns
sigma1_iter_v2 : 0

sigma2         : 210
sigma2_iter    : 210