一个函数能够返回多个不同类型的值吗?

3

我认为从C++函数调用中返回多个值(不同类型!)是很有趣的。

因此,我查找了一些示例代码,但不幸的是,我没有找到任何与此主题相关的内容。

我想要这样一个函数...

int myCoolFunction(int myParam1) {
    return 93923;
}

要处理不同类型的数据并返回多个不同类型的值,例如:

?whatever? myCoolFunction(int myParam1) {
    return { 5, "nice weather", 5.5, myCoolMat }
}

那么使用C++实现这样的功能是否可行呢? (我的想法是使用特殊的AnyType向量,但我找不到示例代码)还是说我必须继续使用这种类型的调用?(见下文)

void myCoolFunction(cv::Mat &myMat, string &str){
   // change myMat
   // change str
}

注意:因此,返回元素的顺序和数量每次都将相同 - > 集合保持不变(如每种情况下的1.:double, 2.:int)。

1
请查看C++模板(可能会有帮助的链接: https://www.tutorialspoint.com/cplusplus/cpp_templates.htm) - Sruthi
你不能在C++中以普通方式完成它,也不能完全泛化,只能创建一个结构体来接受这种类型的参数。 - Arkady Godlin
2
你对C++17的std::any感兴趣吗? - WorldSEnder
你想让你的函数始终返回相同的类型集合,还是根据输入返回不同的类型? - Holt
你的示例看起来像是返回一个 struct,这是可以做到的。 - dbush
是的,集合将保持不变,例如在每种情况下都是 {double, int, string, Mat},可以通过 result[0] 获取 double 值,通过 result[1] 获取 int 值,以此类推。@Holt - user9590073
5个回答

4
如果您想返回多个值,可以返回一个包装不同值的类的实例。
如果您不关心失去语义,可以返回std::tuple1
auto myCoolFunction(int myParam1) {
    return std::make_tuple(5, "nice weather", 5.5, myCoolMat);        
}

如果您想强制类型(例如,使用std::string而不是const char *):
std::tuple<int, std::string, double, cv::Mat> myCoolFunction(int myParam1) {
    return {5, "nice weather", 5.5, myCoolMat};
}

在这两种情况下,您都可以使用 std::get 访问值:

auto tup = myCoolFunction(3);
std::get<0>(tup); // return the first value
std::get<1>(tup); // return "nice weather"

1 如果你有符合C++17标准的编译器,你可以利用模板参数推导,并返回std::tuple{5, "nice weather", 5.5, myCoolMat}


对于C++17,使用auto/std::tuple{...} - Quentin

3
是的,一个函数可以返回不同类型的多个值,在 C++11 标准库中提供了 std::tuple 实现:
#include <tuple>

std::tuple<int, std::string, double, cv::Mat>
myCoolFunction(int myParam1) {
    return { 5, "nice weather", 5.5, myCoolMat }
}

如果你可以使用C++14代码,你甚至不需要声明类型:

#include <tuple>

auto myCoolFunction(int myParam1) {
     return std::make_tuple(5, "nice weather", 5.5, myCoolMat);
}

这里有证明两个版本均可编译(不包括cv::Mat - 我认为GodBolt没有提供它)。

注:

  • 如果使用std::make_tuple,类型可能不是您所期望的。例如,在这种情况下,您将得到一个char *,虽然在显式定义元组时,您可以像我上面一样强制它为std::string。这通常不是问题。
  • 如果某些数据较大,则可以尝试std::move它,以避免复制整个数据,例如传递std::move(myCoolMat)

1
请注意,这两个代码不相等 - 在第二种情况下,返回的类型是std::tuple<int, const char *, double> - Holt
@Holt:是的,这实际上值得明确提及。 - einpoklum

2
你可以返回一个结构体或使用std::tuple。
使用结构体,你可以做到:
myStruct create_a_struct() {
  return {20, std::string("baz"), 1.2f};
}

使用std::tuple

std::tuple<int, std::string, float> create_a_tuple() {
  return {20, std::string("baz"), 1.2f};
}

0

这只是为了娱乐和展示C++的强大而不是其他任何事情。

一种方式,非常邪恶,因为你要求调用方拆开内容,就是使用

std::shared_ptr<void>

作为返回类型。这是允许的,因为std::shared_ptr支持类型擦除。(不幸的是,std::unique_ptr不支持,所以你必须排除它。)

显然,在函数中,你需要使用std::make_shared或类似的函数。

参考:为什么shared_ptr<void>合法,而unique_ptr<void>是不合法的?


-4

返回一个 std::vector,其中 std::variant 是模板参数化为您选择的类型。如果任何类型都是可能的,我不确定为什么您要使用结构来实现而不是直接写入内存空间;因为在结构中没有确定性的对象和类型概念,所以其价值较低。


1
这是一条注释,而不是答案。 - izlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接