Reputation:
It thought it would be interesting to return multiple values (with different types!) from a C++ function call.
So I've looked around to maybe found some example code but unfortunately I could not find anything matching to this topic.
I'd like a function like ...
int myCoolFunction(int myParam1) {
return 93923;
}
to work on different types to return multiple different types of values like
?whatever? myCoolFunction(int myParam1) {
return { 5, "nice weather", 5.5, myCoolMat }
}
So is something like this possible using C++ (My idea was to use a special AnyType-vector but I could not find example code therefore) or do I have to stay on these type of call? (see below)
void myCoolFunction(cv::Mat &myMat, string &str){
// change myMat
// change str
}
Note: So the order and the count of the returned element will be the same every time - > The set stays identical (like 1.:double, 2.:int
in every case)
Upvotes: 3
Views: 4039
Reputation: 132240
Yes, a function can return multiple types of different values, within an std::tuple
, available in the standard library since C++11:
#include <tuple>
std::tuple<int, std::string, double, cv::Mat>
myCoolFunction(int myParam1) {
return { 5, "nice weather", 5.5, myCoolMat }
}
If you're allowed to use C++14 code, you don't even have to declare the type:
#include <tuple>
auto myCoolFunction(int myParam1) {
return std::make_tuple(5, "nice weather", 5.5, myCoolMat);
}
and here is proof both of these versions compile (sans the cv::Mat
- I don't think GodBolt has that available).
Notes:
std::make_tuple
, the types might not be exactly what you expect. For example, in this case you'll get a char *
although when defining the tuple explicitly you could force it to be std::string
like I have above. This is usually not a problem.std::move
it, to avoid copying the whole thing, e.g. passing std::move(myCoolMat)
.Upvotes: 3
Reputation: 37686
If you want to return multiple values, you can return an instance of a class wrapping the different values.
If you do not care about losing semantics, you can return a std::tuple
1:
auto myCoolFunction(int myParam1) {
return std::make_tuple(5, "nice weather", 5.5, myCoolMat);
}
If you want to force the types (e.g., have a std::string
instead of a const char *
):
std::tuple<int, std::string, double, cv::Mat> myCoolFunction(int myParam1) {
return {5, "nice weather", 5.5, myCoolMat};
}
In both cases, you can access the values using std::get
:
auto tup = myCoolFunction(3);
std::get<0>(tup); // return the first value
std::get<1>(tup); // return "nice weather"
1 If you have a C++17 compliant compiler, you can make use of template argument deduction and simply return std::tuple{5, "nice weather", 5.5, myCoolMat}
.
Upvotes: 4
Reputation: 844
Returning a std::vector of std::variant, where std::variant is template parameterized to your selection of types. If any type is actually possible, I'm not sure why you're doing that with structures and not simply writing to the memory space; not having a deterministic concept of the objects and types in the structure has low value.
Upvotes: -4
Reputation: 3244
You can return a structure or use std::tuple.
Using struct, you can do:
myStruct create_a_struct() {
return {20, std::string("baz"), 1.2f};
}
And with std::tuple
std::tuple<int, std::string, float> create_a_tuple() {
return {20, std::string("baz"), 1.2f};
}
Upvotes: 2
Reputation: 234875
(Answer for amusement really and to demonstrate the power of C++ rather than anything else.)
One way, which is really rather evil since you burden the call site with unpicking the contents is to use
std::shared_ptr<void>
as the return type. This is allowed since std::shared_ptr
supports type erasure. (Unfortunately, std::unique_ptr
doesn't so you have to rule that out.)
Clearly though, in the function, you'll need to use std::make_shared
or similar.
Reference: Why is shared_ptr<void> legal, while unique_ptr<void> is ill-formed?
Upvotes: 0