Mark
Mark

Reputation: 55

How to return more than one type from a function?

The backstory. In VBA in Excel I created a function that calculate the shortest distance between two lines (vectors). This function returns the apparent intersection point, and the actual distance between them. To make this work I ended up passing out an array, then sorting out what went where afterwards. It works, but is clunky to read and work with.

In C++ i have made a similar function that returns the point in question.

struct point3D
{ 
double x,y,z;
}
point3D findIntersect(const vec3& vector1, const vec3& vector2)
{
// Do stuff...
return point;
}

The problem: I want to return the length as well, since it uses parts of the original calculation. However most of the time I only want the point.

Possible solutions I have looked at are:

Write a separate function for the distance. A lot of extra work for when I want both of them.

I have seen examples with pairs, but the they look like they have to be the same data type. I essentially want to return a point3D, and a double.

Does anyone have a more elegant solution to returning multiple values from a function?

Upvotes: 4

Views: 337

Answers (6)

Galik
Galik

Reputation: 48615

Straustrup and Sutter are recommending using tuple/tie for this: F.41: Prefer to return tuples to multiple out-parameters

Point3D point3D;
double distance;

std::tie(point3D, distance) = findIntersect(/*..params..*/);

Where:

std::tuple<Point3D, double> findIntersect(/*..params..*/)
{
    Point3D point3D;
    double distance;

    // calculate point3D & distance

    return std::make_tuple(point3D, distance);
} 

Upvotes: 1

USer22999299
USer22999299

Reputation: 5674

I still think that you can and should create the struct for your code (if your code is not a real time..) Stucts are very common and gives you robastics and flexibility in case you would need to expend your code. To be depends on on these key value pair in you code and then realize after few months that you need to change it in 10 places... :)

Upvotes: -2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726579

C++ lets you overload the function, i.e. use the same name, but different parameter types. You can return point3D as the return value, and make the length reference parameter appear "optional" by providing a separate overload:

point3D findIntersect(const vec3& vector1, const vec3& vector2) {
    double ignore;
    return findIntersect(vector1, vector2, ignore);
}
point3D findIntersect(const vec3& vector1, const vec3& vector2, double &length) {
    ... // Implementation goes here
}

Callers who don't want to get the length back would call the two-argument overload, while the callers who want the length would call the three-argument one. In both cases the implementation is going to be the same, with the two-argument call providing a reference to an ignored variable for the length.

Upvotes: 1

Since you don't want to define a custom struct or class, I assume that you want the return value to be only point. So, I suggest you to use an optional pointer argument, it's default value is NULL, and if it is not NULL you store the distance in the variable pointed by it.

point3D findIntersect(const vec3 &v1, const vec3 &v2, double *dist = NULL) {
  // ...
  if (dist) {
    // find the distance and store in *dist
  }
  return ... ;
}

Upvotes: 2

tstark81
tstark81

Reputation: 488

You sure can use pairs.

std::pair<point3D, double> findIntersect(const vec3& vector1, const vec3& vector2);

Upvotes: 0

Marius Bancila
Marius Bancila

Reputation: 16328

You could use a std::pair<point3D, double>. There is also a std::tuple, when you need to return more than two values. (Notice there is no such thing as same type for the pair or tuple values, as you mentioned.)

Upvotes: 0

Related Questions