【问题标题】:Can a function return multiple values of varying types?一个函数可以返回多个不同类型的值吗?
【发布时间】:2018-04-10 15:03:55
【问题描述】:

它认为从 C++ 函数调用返回多个值(具有不同类型!)会很有趣。

所以我四处寻找可能找到了一些示例代码,但不幸的是我找不到与该主题匹配的任何内容。

我想要一个类似...的函数

int myCoolFunction(int myParam1) {
    return 93923;
}

处理不同类型以返回多种不同类型的值,例如

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

使用 C++ 可以实现这样的事情 (我的想法是使用特殊的 AnyType-vector,但我因此找不到示例代码) 还是我必须继续使用这些类型的调用? (见下文)

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

注意:所以每次返回元素的顺序和计数都相同 - > 集合保持相同(如1.:double, 2.:int 在每种情况下)

【问题讨论】:

  • 查看 C++ 中的模板(有用的链接可能是:tutorialspoint.com/cplusplus/cpp_templates.htm
  • 你不能在 c++ 中以普通的方式来做,而不是完全通用的方式,只能创建一个结构,除了这种参数。
  • 我可以让你对 c++17 的 std::any 感兴趣吗?
  • 您希望您的函数始终返回同一组类型,还是希望您的函数根据输入返回不同类型?
  • 你的例子看起来像返回一个struct,你可以这样做。

标签: c++ function return-type multiple-return-values


【解决方案1】:

是的,一个函数可以在 std::tuple 中返回多种类型的不同值,自 C++11 起在标准库中可用:

#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);
}

here is proof both of these versions compile(没有cv::Mat - 我认为GodBolt 没有可用的)。

注意事项:

  • 如果您使用std::make_tuple,则类型可能与您期望的不完全一致。例如,在这种情况下,您将得到一个char *,尽管在明确定义元组时,您可以强制它为std::string,就像我上面所说的那样。这通常不是问题。
  • 如果某些数据很大,您可以尝试std::move,以避免复制整个数据,例如通过std::move(myCoolMat)

【讨论】:

  • 注意,这两个代码是不等价的——第二种情况,返回的类型是std::tuple&lt;int, const char *, double&gt;
  • @Holt:是的,这实际上值得一提。
【解决方案2】:

如果要返回多个值,可以返回包装不同值的类的实例。

如果你不关心丢失语义,你可以返回一个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 的编译器,你可以使用 template argument deduction 并简单地返回 std::tuple{5, "nice weather", 5.5, myCoolMat}

【讨论】:

  • auto/std::tuple{...} 用于 C++17。
【解决方案3】:

您可以返回一个结构或使用 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};
}

【讨论】:

    【解决方案4】:

    返回 std::variant 的 std::vector,其中 std::variant 是模板参数化为您选择的类型。如果任何类型实际上是可能的,我不确定你为什么要使用结构而不是简单地写入内存空间;对结构中的对象和类型没有确定性概念的价值很低。

    【讨论】:

    • 这是评论,不是答案。
    【解决方案5】:

    (真正娱乐的答案,并展示 C++ 的力量,而不是其他任何东西。)

    一种非常邪恶的方法是使用

    std::shared_ptr&lt;void&gt;

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

    但很明显,在函数中,您需要使用 std::make_shared 或类似名称。

    参考:Why is shared_ptr<void> legal, while unique_ptr<void> is ill-formed?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-04
      • 1970-01-01
      • 2021-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-16
      • 1970-01-01
      相关资源
      最近更新 更多