0

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?

innosam
  • 427
  • 1
  • 5
  • 18
  • *As we know that output parameters are really bad thing* Do we? Can you further explain what you mean by that statement? What do you refer to as *output parameter*, why is it bad? – David Rodríguez - dribeas Aug 22 '13 at 20:36
  • There had been discussion on this in length, you can refer to http://stackoverflow.com/questions/18157090/how-to-avoid-the-copy-when-i-return/ to know more about it!!! – innosam Aug 22 '13 at 20:40
  • So by output parameter you mean passing by modifiable reference or pointer, right? At any rate while there are some reasons to prefer returning by value in many circumstances, that does not mean that output arguments are discredited. You can still use them, and if in your design it makes sense and you already have an implementation for it, just use it. There are places where output arguments are *mandated* by the coding guidelines (shops that target C++03 compilers, for example) – David Rodríguez - dribeas Aug 22 '13 at 20:45
  • Yes you are spot on! Thanks – innosam Aug 22 '13 at 20:54

2 Answers2

1

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.

MasterPlanMan
  • 992
  • 7
  • 14
  • 1
    Check this out: http://stackoverflow.com/questions/18157090/how-to-avoid-the-copy-when-i-return/ – innosam Aug 22 '13 at 19:58
  • Pointers are usually no good (unless well encapsulated) and this is C++ no java or C# (btw: C# and java have pointers, only) –  Aug 22 '13 at 20:02
  • ... besides some value classes –  Aug 22 '13 at 20:03
  • Available feature doesn't make it better. It may be quite subjective, but I feel like explicitly declaring the output parameters in the function declaration is easier to follow than having to check the constructors of the classes being used. As far as I'm concerned, I prefer the way you've done it and I feel most programmers feel the same way. I just feel those features are making c++ more and more like perl, that is getting more criptic just so the code looks better, not easier to understand. As for pointers, that's why it's usually better to use references. – MasterPlanMan Aug 22 '13 at 20:05
  • It's not that the object is kept alive even though the destructor was called, it's that the lifetime of the temporary is extended to the lifetime of the reference that is binding it. – SirGuy Aug 22 '13 at 20:25
  • When you say *output parameter*, what are you referring to? `T f()` or `void f(T&)` (alternatively `void f(T*)`)? I cannot make sense of the statement: *you can use a const reference as an output parameter*, and I quite feel like you cannot really do that, but I might be misinterpreting what you mean by those terms. – David Rodríguez - dribeas Aug 22 '13 at 20:53
  • My understanding of an output is that it's a value set inside the function and made available to the caller - be it the return statement or the the function parameters (references, pointers, etc). – MasterPlanMan Aug 23 '13 at 14:17
1

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.

DubiousPusher
  • 1,132
  • 2
  • 8
  • 19
  • 1
    This reminds me of another idea. Make the function a class's constructor and use it as follows: GetCombinations( ... ).result(). It would only be worth while if NRVO does not happen and one can't rely on move constructors. – Werner Erasmus Aug 22 '13 at 20:27