Suggestion: return std::tuples instead of input parameters

Hi, I made this suggestion in JIRA, but it is abstract enough that it would be beneficial to discuss it on the forum. Here is the original JIRA issue: sft.its.cern.ch/jira/browse/ROOT-6941

Here is copy-pasted the content of the original JIRA post:

There are several functions and methods in ROOT that use the technique of output parameters, when a parameter is passed by non-const reference in order to be modified. This is done because C++ did not easily allow multiple values to be returned by a function.

This is changed with C++11 with make_pair, make_tuple, and std::tie making it very convenient to have functions with multiple return values (without needing to make a whole custom struct for the purpose).

My proposal would not break any existing code, as it merely adds overloads. Any function that currently takes non-const ref parameters should be overloaded to have an equivalent function returning an std::pair or std::tuple. E.g. for TF1::GetRange, we currently have:

virtual void GetRange(Double_t& xmin, Double_t& xmax) const
My proposal would add: virtual std::pair<double,double> GetRange() const

A TF2 could instead return an std::tuple<double,double,double,double>, etc. Functions which currently take a mix of input and output parameters could be accomodated the same way. Probably there are some cases where there is ambiguity, but the users could fall back to the input arguments for those cases.

This would be one small step towards making ROOT coding styles more modern, and would make use of output-parameter functions in PyROOT much less cumbersome.

Hi,

I’m actually thinking that for the benefit of Python part, these can be done in the generated wrapper.

Cheers,
Wim

The only drawback I see is that programming will be more obscure. The receiver of the std::pair or std::tuple will need to understand the meaning of each element in the tuple, which is accessed by a positional index and not by a name. Wouldn’t it be better to return a simple struct TF1::Range { double xmin; double xmax;} ?

Hi,

that’s even true for input from C++:TF1::Range r; tf1->GetRange(r); // or tf1->GetRange(&r);allows that same clarity. Also, “TF1::Range r = tf1->GetRange();” isn’t as expensive as it used to be. Not b/c of C++11, but b/c of the changed calling conventions for 64b, allowing the return values of the struct to be picked up from the SSE registers (xmm). In fact, trying it out with gcc at -O3, the return is no different for all three options, but the call has an extra address calculation (leaq) for the passing of the Range by reference, and two for passing the doubles by reference.

Cheers,
Wim