Reputation: 55
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.
function(const argin1, const argin2, argout&, argout2&)
. Just ugh! Would require the user to always expect every variable out.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
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
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
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
Reputation: 1830
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
Reputation: 488
You sure can use pairs.
std::pair<point3D, double> findIntersect(const vec3& vector1, const vec3& vector2);
Upvotes: 0
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