<Advanced>(Hey, if the previous two posts are advanced, then I figure this qualifies as well.)
C++ does sort of support tuples natively, because you can make and return structures, but they have to have a specific size, and a type for each returned value. You
cannot return an array, and returning a pointer is generally speaking a bad idea (what are you going to point it at? Keep in mind that the function's local variables are dead when the function returns; 'normal' returns only work because a copy is made, at least conceptually.)
If you are returning several values
of the same type, (or, with a bit more effort, where all of them are objects with a common base class), you can return a container of those objects such as a std::vector of them.
Otherwise... if you are lazy ;) or if the structure won't be used anywhere else, you can rely on the standard library. If you only need two return values, you can return a std::pair. This is a templated structure that has two members, 'first' and 'second'.
// Sample implementation: this is what std::pair MIGHT look like in your// library implementation.namespace std { template <typename T1, typename T2> struct pair { T1 first; T2 second; }; template <typename T1, typename T2> std::pair<T1, T2> make_pair(const T1& x, const T2& y) { std::pair<T1, T2> result; result.first = x; result.second = y; return result; }}
See, the standard library already gives an example of the technique ;) (The reason std::make_pair() exists is so that you don't have to specify the template types when you create a std::pair object. Functions are able to infer template types from their arguments, but class constructors can't.)
"Unfortunately" the standard library doesn't provide a generic structure for three or more items. You *could*, however, abuse std::pair to do it:
typedef std::pair<std::pair<int, int>, int> triple;triple giveMeThreeInts() { return std::make_pair(std::make_pair(1, 2), 3);}int main() { triple t = giveMeThreeInts(); int x = t.first.first; int y = t.first.second; int z = t.second;}
The Boost library, among others, provides a templated tuple class holding up to some particular number of items, which is (AFAIK) basically a wrapper for this technique.
<OPINION>But you're probably better off declaring a struct in that case.
Anyway, there are many ways to handle "returning multiple things", but as always, just because you CAN do something doesn't mean you SHOULD. Whenever it looks like a multiple return is required, always think carefully about your approach, and try to at least keep things organized.
Personally I think it's a bad idea to use the return value as a "real" return value if you will also use an out-parameter (i.e. passing something by reference and modifying it). Go for all-or-nothing; sometimes you will decide to use the return value for an error code, instead.
Sometimes, taking the "return error code and modify reference parameters" approach is a good idea even for only one return value. This is especially the case if it helps out with template parameter inference ;) But usually, you'll want to throw an exception to indicate an error anyway. As well, a function that returns a value can be used to initialize a variable, whereas if you want a variable's initial value to come from a function that uses an out-parameter, then you have to declare the variable first and then call the function with the uninitialized variable. This is quite ugly.
Oh, and about the vector returns: Some people will tell you never to return a standard library container, but instead always use out-parameters for them. This is an optimization technique (which already marks it as evil ;) ), and assumes that the calling code might already have a vector instance handy, into which the called code will dump its stuff. However, this complicates the interface, firstly because the calling code might have to declare a local vector that it wouldn't have anyway, and secondly because you have to decide whether the called code will clear out any existing items, blindly trust that there are none, or deliberately assume there may be some and append to the existing set. Plus, it's quite likely not to help in terms of optimization anyway. :)
</OPINION></ADVANCED>