C++: Return multiple values of different types from a function
Having done a lot of programming in C++0x and then spending a lot of time on Python programming. I got used to a lot of features in Python and remembered how tedious it is to get the things done in C++. Mind you C++ is definitely faster of the two.
One of the Python features I like the most, is the ability to return multiple values of different types from a function. In Python, when you return multiple values of different types from a function you are actually returning a tuple.
I was happy to find out that since C++11 there is support for a fixed-size collection of heterogeneous values called tuple. The characteristics of a tuple is very similar in Python and C++.
To use a tuple in C++ you have to include the header #include <tuple>
.
Here is an example of a function that returns a tuple.
#include <iostream>
#include <tuple>
#include <string>
std::tuple<int, bool, std::string> returnTuple() {
return std::tuple<int, bool, std::string>{100, true, "Error Message"};
}
int main() {
std::tuple<int, bool, std::string> t = returnTuple();
std::cout << "int=" << std::get<0>(t) << std::endl;
std::cout << "bool=" << std::get<1>(t) << std::endl;
std::cout << "string=" << std::get<2>(t) << std::endl;
}
// Output
// int=100
// bool=1
// string=Error Message
A shorter way to make a tuple is by using std::make_tuple
, where you don't have to specify the data types. However, in this case they need to match the return type.
std::tuple<int, bool, std::string> returnTuple() {
return std::make_tuple(100, true, "Error Message");
}
The compiler tries to convert the values to a data type that matches the return type.
std::tuple<int, bool, std::string> returnTuple() {
return std::make_tuple(100.0, 5, "Error Message");
}
// Output
// int=100 Fraction gets converted to whole number
// bool=1 Anything not equal to zero gets converted to one or true
// string=Error Message
And if the value cannot be implicitly converted they you get a conversion error during compilation.
std::tuple<int, bool, std::string> returnTuple() {
return std::make_tuple(100.0, 5, 'c');
// Compilation error: no viable conversion
}
To access an element in tuple by index you make use of std::get
.
int main() {
std::tuple<int, bool, std::string> t = returnTuple();
std::cout << "int=" << std::get<0>(t) << std::endl;
std::cout << "bool=" << std::get<1>(t) << std::endl;
std::cout << "string=" << std::get<2>(t) << std::endl;
}
Now, if you already have variables defined in which you want to capture the values from a function that returns a tuple. You need to use std::tie
.
int main() {
int i;
bool b;
std::string str;
std::tie(i, b, str) = returnTuple();
}
If you want to ignore some elements of the returned tuple, then literally use std::ignore
.
int main() {
int i;
bool b;
std::tie(i, b, std::ignore) = returnTuple();
}
One last thing, to concatenate tuples you can use std::tuple_cat
.
std::tuple<int, bool, std::string> t1(100, true, "Error Message");
auto bigtuple = std::tuple_cat(t1, std::make_tuple("Foo", "bar"));
std::cout << "bigtuple[3] = " << std::get<3>(bigtuple) << std::endl;
// Output
// bigtuple = Foo