Live data from Hacker News

Returning multiple values from functions in C++

eli.thegreenplace.net

11–20 of 67 posts

Re: Returning multiple values from functions in C++

#11

I know it's mentioned specially in the article but the C programmer in me immediately wants to use structs. They don't need to be complex or long lived or even initialized. And as a bonus there's no heap involved anywhere. Either that or just bail out of c++ and use go.

std::tuple is essentially an "anonymous" struct -- there's no allocation involved

[deleted]

Re: Returning multiple values from functions in C++

#12

I know it's mentioned specially in the article but the C programmer in me immediately wants to use structs. They don't need to be complex or long lived or even initialized. And as a bonus there's no heap involved anywhere. Either that or just bail out of c++ and use go.

std::tuple is essentially an "anonymous" struct -- there's no allocation involved

But the members inside don't have proper names.

Re: Returning multiple values from functions in C++

#13

I know it's mentioned specially in the article but the C programmer in me immediately wants to use structs. They don't need to be complex or long lived or even initialized. And as a bonus there's no heap involved anywhere. Either that or just bail out of c++ and use go.

std::tuple is essentially an "anonymous" struct -- there's no allocation involved

[deleted]

Re: Returning multiple values from functions in C++

#15
Ada has in, out and in/out parameters which adds a little more semantic to C and C++'s pointer parameters.

Author mentions Common Lisp's multiple values, and one of the main feature of multiple values is that they are optional: the caller does not need to use secondary values. Even though floor returns 2 values, the following is a valid expression:

   (+ (floor x) 2)
Only the primary value is used. A compiler typically generates code that use registers: the program does not allocate memory to wrap return values in list or a structure (all values are still computed, but secondary values are often additional data that a function needs to compute to determine its primary result).

Re: Returning multiple values from functions in C++

#16
post #4

The getline case (boolean and possible value) really wants a type like Haskell's "Maybe" or Rust's Option: a type that either contains nothing or a value.

Unfortunately the currently available solution (boost::optional) performs enough worse that the difference can be measured in a simple implementation of "wc -l". Consider the following code: #include #include #include using namespace std; using namespace boost; optional getline_(istream &st) { std::string line; if(getline(st, line)) return line; return none; } int main() { int lines = 0; while(getline_(cin)) lines++;…

[deleted]

Re: Returning multiple values from functions in C++

#17

The getline case (boolean and possible value) really wants a type like Haskell's "Maybe" or Rust's Option: a type that either contains nothing or a value.

In this case, passing the std::string to std::getline by reference is more than just an "out parameter": it is the buffer in which the result should be stored. Of course this will be more efficient than allocating a new buffer for each line -- and that is a good reason why this particular interface would be worse off with multiple return values.

The std::unordered_map::insert example in the article is an excellent example of an interface with multiple return values: it returns a pair (iterator, bool) of an iterator to the given key and a bool indicating if the iterator is to a newly inserted key-value pair or if it was the key-value pair already stored in the map. Neither the iterator nor the bool owns a buffer like in the std::getline example, so the std::getline out parameter design is not needed here.

Re: Returning multiple values from functions in C++

#18

Instead of markers, I like to use typedefs instead. Here's an example how this would look like in a HPC related program. Basically, if you know Fortran, you know where this is coming from. typedef const double * const __restrict__ IN; typedef double * const __restrict__ OUT; typedef const int INT_VALUE; typedef const double FP_VALUE; void diffuse_c( OUT runtime_total_s, OUT runtime_boundary_s, OUT thermal_energy_upda…

I can't be the only one who finds "INT_VALUE" both superfluous and unnecessarily ugly?

Re: Returning multiple values from functions in C++

#19

I know it's mentioned specially in the article but the C programmer in me immediately wants to use structs. They don't need to be complex or long lived or even initialized. And as a bonus there's no heap involved anywhere. Either that or just bail out of c++ and use go.

I prefer to use generic structures (tuples, pairs etc.) or return proper type. One time structs are usually redeclared on multiple places. It is really hard maintain such code.

Re: Returning multiple values from functions in C++

#20
post #18

Instead of markers, I like to use typedefs instead. Here's an example how this would look like in a HPC related program. Basically, if you know Fortran, you know where this is coming from. typedef const double * const __restrict__ IN; typedef double * const __restrict__ OUT; typedef const int INT_VALUE; typedef const double FP_VALUE; void diffuse_c( OUT runtime_total_s, OUT runtime_boundary_s, OUT thermal_energy_upda…

I can't be the only one who finds "INT_VALUE" both superfluous and unnecessarily ugly?

You're right, I have been thinking about this naming as well. I think in this context, "INT_PARAM" would be better. I like to typedef it because this way it's easier to replace with a hardware specific integer type later on if I decide to do so. Anyways, the "VALUE" naming is coming from Fortran, which is by default pass-by-reference, so you use it to get pass-by-value.

Edit: Thinking about it some more, "INT_VALUE" still makes sense - it makes it clear that this specific symbol should be accessed as a value, not as a pointer. Doing this reminds me that I'm (probably) imposing more register pressure by passing by value. In general I'd probably pass a const int * const pointer here, but in this specific case I needed values because of some CUDA specific limitation.

Post reply on HN