The
POSIX libraries are replete with such sets of functions. Overloading won't do in this case because you can't define overloaded versions of a function that differ only in their return types:
int convert_filename(const char* path);
FILE* convert_filename(const char* path); //error
By using a tuple type to pack the two return types, you can simulate multiple return types for a single function. As always, use a
typedef to hide the cumbersome syntax:
typedef tuple<int, FILE *> file_t;
file_t convert_filename(const char* path);
In an object-oriented environment you can extend
file_t to accommodate an
fstream object as well.
A tuple type provides a neat solution to another problem that I presented here several months ago, namely simulating floating point values with integers. Instead of using two bare integers, you can now use a tuple:
typedef tuple<__int64, int> Currency;
The revised class USD now looks like this:
class USD
{
private:
Currency curr;
public:
explicit USD(__int64 d=0, int c=0): curr(d,c) {}
//..
};
As an aside, notice how important it is to declare data members private. Users of this class won't notice that its implementation has changed because the interface remains intact.
This is very nice, but you're probably asking: "Can't I just pack the two integers in a good ol' struct instead?" Of course you can. However, a tuple offers a bonus: it already overloads the relational operators <, >, ==, etc. Consequently, you can compare two currency values without any effort:
bool operator==(const USD& u1, const USD& u2)
{
return u1.curr==u2.curr;
}
The tuple's overloaded
== returns true if and only if each element in
u1 is equal to the corresponding element in
u2. For example:
Currency curr1(100,99);
Currency curr2(100,98);
Currency curr3(100,98);
bool res=curr1==curr2; //false
res=curr2==curr3; //true
The Top of the Poll
Tuples have many other uses. For example, you can create a tuple of references and cv-qualified types:
int i; char c;
make_tuple(ref(i),ref(c)); // tuple <int &, char&>
make_tuple(cref(i), c); // tuple <const int &, char>
The
ref class template serves a reference wrapper. Likewise,
cref wraps a reference to a
const object. To simplify the creation of tuples of reference elements, use the
tie() function:
tie(i, c); //same as: make_tuple(ref(i), ref(c));
A tuple containing non-const reference elements can be used to "unpack" another tuple into real objects:
tie(i, c)=make_tuple(1, 'a');
After the assignment,
i=1 and
c='a'. This technique may be useful when unpacking a function that returns a tuple.