How can i avoid output parameters while doing backtracking?

222 Views Asked by At

As we know that output parameters are really bad thing

 void foo(set<int> *x)

Here x is actually expected parameters, this is pretty common practice in Linux system calls. But for c++ this seems not be a good coding practice.

I have a scenario, where i have to backtrack through a list of list of strings, and return all possible combination of strings from each list.

 a b 
 d e 
 f g
 Possible combinations are:
    a d f, a d g, a e f, a e g, etc...

list<list<string> > parameters;

A straightforward backtracking solution would be:

    void  getCombinations(list<list<string> > &param, 
          list<list<string> >::iterator it, 
          vector<string> &backtracker, 
          list<vector<string> > &output){

          if(it == param.end()){
              output.append(backtracker);
          }
          for(auto i = it->begin; i!= it->end(); i++){
            backtracker.push_back(*i);
             getCombinations(param, it+1, backtracker, output)
            backtracker.pop_back();
          }
         }

Now, How can i avoid output parameters here, such that i could return the output list?

2

There are 2 best solutions below

1
On

Output parameters show up all the time in C++. You could however encapsulate the output datastructure with the methods.

class ComboGenerator {
public:
  void getCombinations(list<list<string> > &param, 
    list<list<string> >::iterator it, 
    vector<string> &backtracker){

    if(it == param.end()){
      result.append(backtracker);
    }
    for(auto i = it->begin; i!= it->end(); i++){
      backtracker.push_back(*i);
      getCombinations(param, it+1, backtracker)
      backtracker.pop_back();
    }
  }

  list<list<string>> &getResult() { return result; }

private:
  list<list<string>> result;    
};

My experience is that 95% of the time someone is soapboxing about practices it's personal peevishness. The other 5% of the time it's good good sense.

7
On

As far as I know, output parameters is a good practice depending on what you're doing. That's what pointers or references are for. And that's why java or C# uses references on objects by default. Better performances, easier to use, etc etc.

Edit: In case you really do want to do that though, you can use a const reference as an output parameter. As long as it's a const reference, it will be kept alive even though the referenced object's destructor was called in the code.

You can can also define the copy, move constructors properly (meaning you need to create a wrapper class over the lists) as you said earlier.