Question

Boost::Tuples vs Structs for return values

I'm trying to get my head around tuples (thanks @litb), and the common suggestion for their use is for functions returning > 1 value.

This is something that I'd normally use a struct for , and I can't understand the advantages to tuples in this case - it seems an error-prone approach for the terminally lazy.

Borrowing an example, I'd use this

struct divide_result {
    int quotient;
    int remainder;
};

Using a tuple, you'd have

typedef boost::tuple<int, int> divide_result;

But without reading the code of the function you're calling (or the comments, if you're dumb enough to trust them) you have no idea which int is quotient and vice-versa. It seems rather like...

struct divide_result {
    int results[2]; // 0 is quotient, 1 is remainder, I think
};

...which wouldn't fill me with confidence.

So, what are the advantages of tuples over structs that compensate for the ambiguity?

 45  11869  45
1 Jan 1970

Solution

 25

tuples

I think i agree with you that the issue with what position corresponds to what variable can introduce confusion. But i think there are two sides. One is the call-side and the other is the callee-side:

int remainder; 
int quotient;
tie(quotient, remainder) = div(10, 3);

I think it's crystal clear what we got, but it can become confusing if you have to return more values at once. Once the caller's programmer has looked up the documentation of div, he will know what position is what, and can write effective code. As a rule of thumb, i would say not to return more than 4 values at once. For anything beyond, prefer a struct.

output parameters

Output parameters can be used too, of course:

int remainder; 
int quotient;
div(10, 3, &quotient, &remainder);

Now i think that illustrates how tuples are better than output parameters. We have mixed the input of div with its output, while not gaining any advantage. Worse, we leave the reader of that code in doubt on what could be the actual return value of div be. There are wonderful examples when output parameters are useful. In my opinion, you should use them only when you've got no other way, because the return value is already taken and can't be changed to either a tuple or struct. operator>> is a good example on where you use output parameters, because the return value is already reserved for the stream, so you can chain operator>> calls. If you've not to do with operators, and the context is not crystal clear, i recommend you to use pointers, to signal at the call side that the object is actually used as an output parameter, in addition to comments where appropriate.

returning a struct

The third option is to use a struct:

div_result d = div(10, 3);

I think that definitely wins the award for clearness. But note you have still to access the result within that struct, and the result is not "laid bare" on the table, as it was the case for the output parameters and the tuple used with tie.

I think a major point these days is to make everything as generic as possible. So, say you have got a function that can print out tuples. You can just do

cout << div(10, 3);

And have your result displayed. I think that tuples, on the other side, clearly win for their versatile nature. Doing that with div_result, you need to overload operator<<, or need to output each member separately.

2009-01-03

Solution

 10

Another option is to use a Boost Fusion map (code untested):

struct quotient;
struct remainder;

using boost::fusion::map;
using boost::fusion::pair;

typedef map<
    pair< quotient, int >,
    pair< remainder, int >
> div_result;

You can access the results relatively intuitively:

using boost::fusion::at_key;

res = div(x, y);
int q = at_key<quotient>(res);
int r = at_key<remainder>(res);

There are other advantages too, such as the ability to iterate over the fields of the map, etc etc. See the doco for more information.

2009-01-03