C++ 11中元组有哪些好的用例?

zvr*_*rba 41 c++ tuples c++11

在C++ 11中使用元组有什么好的用例?例如,我有一个定义本地结构的函数,如下所示:

template<typename T, typename CmpF, typename LessF>
void mwquicksort(T *pT, int nitem, const int M, CmpF cmp, LessF less)
{
  struct SI
  {
    int l, r, w;
    SI() {}
    SI(int _l, int _r, int _w) : l(_l), r(_r), w(_w) {}
  } stack[40];

  // etc
Run Code Online (Sandbox Code Playgroud)

我正在考虑SI用一个替换结构std::tuple<int,int,int>,这是一个更短的声明,方便的构造函数和运算符已经预定义,但具有以下缺点:

  • 元组元素隐藏在模糊的,实现定义的结构中.即使Visual Studio很好地解释和显示它们的内容,我仍然不能放置依赖于元组元素值的条件断点.
  • 访问单个元组字段(get<0>(some_tuple))比访问struct元素(s.l)要冗长得多.
  • 按名称访问字段比通过数字索引提供更多信息(并且更短!).

最后两点由tie函数解决.鉴于这些缺点,元组的用例是什么?

更新事实证明VS2010 SP1调试器无法显示以下数组的内容std::tuple<int, int, int> stack[40],但它在使用结构编码时工作正常.所以这个决定基本上是一个明智的选择:如果你必须检查它的值,使用一个结构[特别是.像GDB这样的调试器很重要].

mir*_*irk 58

这是从函数返回多个值的简单方法;

std::tuple<int,int> fun();
Run Code Online (Sandbox Code Playgroud)

结果值可以优雅地使用如下:

int a;
int b;
std::tie(a,b)=fun();
Run Code Online (Sandbox Code Playgroud)


Kil*_*nDS 26

嗯,imho,最重要的部分是通用代码.编写适用于各种结构的通用代码要比编写处理元组的泛型要困难得多.例如,std::tie你自己提到的功能几乎不可能用于结构.

这允许你做这样的事情:

  • 存储延迟执行的函数参数(例如这个问题)
  • 返回多个参数,无需繁琐(un)打包 std::tie
  • 组合(非等同类型)数据集(例如来自并行执行),可以简单地完成std::tuple_cat.

问题是,它不会因这些用途而停止,人们可以在这个列表上进行扩展,并根据结构更难以处理的元组编写通用功能.谁知道,也许明天有人为序列化目的找到了很好的用途.


LB-*_*B-- 20

我认为tuples的大部分用途来自std::tie:

bool MyStruct::operator<(MyStruct const &o) const
{
    return std::tie(a, b, c) < std::tie(o.a, o.b, o.c);
}
Run Code Online (Sandbox Code Playgroud)

以及答案中的许多其他示例.我发现这个例子是最常用的,因为它比以前在C++ 03中节省了很多精力.


Jon*_*ely 13

你用过std::pair吗?您使用的许多地方std::tuple都很相似,但不限于两个值.

您列出的元组的缺点也适用于标准::对,有时候你想要一个更具表现力与类型为会员优于名称firstsecond,但有时你并不需要这一点.这同样适用于元组.


igo*_*ord 11

我认为除了一些通用库特性的实现细节之外,元组没有很好用.

键入的(可能的)节省不会抵消结果代码的自记录属性的损失.

将元组替换为仅占用字段的有意义名称的结构,将字段名称替换为"数字"(就像std :: pair的错误概念一样).

使用元组返回多个值远不如自我文档那么替代 - 返回命名类型或使用命名引用.如果没有这种自我记录,如果它们是可相互转换的,则很容易混淆返回值的顺序.

  • 按顺序传递参数并不比使用元组返回多个值好多少。您仍然可能会混淆参数的顺序。但至少每个参数都有自己的名称。元组的值则不然。 (2认同)

小智 6

真实的用例是你有不可命名的元素 - 可变参数模板和lambda函数的情况.在这两种情况下,您都可以使用未知类型的未命名元素,因此存储它们的唯一方法是使用未命名元素的结构:std :: tuple.在其他所有情况下,您都拥有已知类型的已知#名称元素,因此可以使用普通结构,这在99%的情况下都是优秀的结果.

例如,您不应该使用std :: tuple从具有固定数量的通用输入的普通函数或模板中获得"多次返回".使用真实的结构.一个真实的对象比std :: tuple cookie-cutter更加"通用",因为你可以在任何界面上给出一个真正的对象.它还将为您提供更多类型安全性和公共图书馆的灵活性.

只需比较这两个类成员函数:

std::tuple<double, double, double>  GetLocation() const; // x, y, z

GeoCoordinate  GetLocation() const;
Run Code Online (Sandbox Code Playgroud)

使用真正的"地理坐标"对象,我可以提供一个操作符bool(),如果父对象没有位置,则返回false.通过其API,用户可以获得x,y,z位置.但这是最重要的事情 - 如果我决定通过在6个月内添加时间字段来制作GeoCoordinate 4D,那么当前用户的代码将不会中断.我不能用std :: tuple版本做到这一点.