C++11 中元组有哪些好的用例?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10259351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What are good use-cases for tuples in C++11?
提问by zvrba
What are good use-cases for using tuples in C++11? For example, I have a function that defines a local struct as follows:
在 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
I was considering to replace the SI
struct with an std::tuple<int,int,int>
, which is a far shorter declaration with convenient constructors and operators already predefined, but with the following disadvantages:
我正在考虑SI
用 an替换结构体std::tuple<int,int,int>
,这是一个更短的声明,已经预定义了方便的构造函数和运算符,但有以下缺点:
- Tuple elements are hidden in obscure, implementation-defined structs. Even though Visual studio interprets and shows their contents nicely, I still can't put conditional breakpoints that depend on value of tuple elements.
- Accessing individual tuple fields (
get<0>(some_tuple)
) is far more verbose than accessing struct elements (s.l
). - Accessing fields by name is far more informative (and shorter!) than by numeric index.
- 元组元素隐藏在模糊的、由实现定义的结构中。即使 Visual Studio 很好地解释和显示了它们的内容,我仍然不能放置依赖于元组元素值的条件断点。
- 访问单个元组字段 (
get<0>(some_tuple)
) 比访问结构元素 (s.l
)要冗长得多。 - 按名称访问字段比按数字索引提供更多信息(而且更短!)。
The last two points are somewhat addressed by the tie
function. Given these disadvantages, what would be a good use-case for tuples?
最后两点在某种程度上由该tie
函数解决。鉴于这些缺点,元组的良好用例是什么?
UPDATETurns out that VS2010 SP1 debugger cannot show the contents of the following array std::tuple<int, int, int> stack[40]
, but it works fine when it's coded with a struct. So the decision is basically a no-brainer: if you'll ever have to inspect its values, use a struct [esp. important with debuggers like GDB].
UPDATE结果发现 VS2010 SP1 调试器无法显示以下数组的内容std::tuple<int, int, int> stack[40]
,但是当它用结构编码时它可以正常工作。所以这个决定基本上是轻而易举的:如果你必须检查它的值,使用结构 [esp. 对于像 GDB 这样的调试器很重要]。
采纳答案by KillianDS
Well, imho, the most important part is generic code. Writing generic code that works on all kinds of structs is a lot harder than writing generics that work on tuples. For example, the std::tie
function you mentioned yourself would be very nearly impossible to make for structs.
好吧,恕我直言,最重要的部分是通用代码。编写适用于各种结构的泛型代码比编写适用于元组的泛型要困难得多。例如,std::tie
您自己提到的函数几乎不可能用于结构。
this allows you to do things like this:
这允许你做这样的事情:
- Store function parameters for delayed execution (e.g. this question)
- Return multiple parameters without cumbersome (un)packing with
std::tie
- Combine (not equal-typed) data sets (e.g. from parallel execution), it can be done as simply as
std::tuple_cat
.
- 存储延迟执行的函数参数(例如这个问题)
- 返回多个参数而无需繁琐的(un)打包
std::tie
- 合并(不同类型的)数据集(例如来自并行执行),它可以像
std::tuple_cat
.
The thing is, it does not stop with these uses, people can expand on this list and write generic functionality based on tuples that is much harder to do with structs. Who knows, maybe tomorrow someone finds a brilliant use for serialization purposes.
问题是,它并不止于这些用途,人们可以扩展这个列表并编写基于元组的通用功能,而这对于结构来说要困难得多。谁知道呢,也许明天有人会发现序列化用途的绝妙用途。
回答by mirk
It is an easy way to return multiple values from a function;
这是一种从函数返回多个值的简单方法;
std::tuple<int,int> fun();
The result values can be used elegantly as follows:
结果值可以优雅地使用如下:
int a;
int b;
std::tie(a,b)=fun();
回答by LB--
I think most use for tuple
s comes from std::tie
:
我认为tuple
s 的大部分用途来自std::tie
:
bool MyStruct::operator<(MyStruct const &o) const
{
return std::tie(a, b, c) < std::tie(o.a, o.b, o.c);
}
Along with many other examples in the answers here. I find this example to be the most commonly useful, however, as it saves a lot of effort from how it used to be in C++03.
以及此处答案中的许多其他示例。然而,我发现这个例子最有用,因为它比以前在 C++03 中的方式节省了很多工作。
回答by Jonathan Wakely
Have you ever used std::pair
? Many of the places you'd use std::tuple
are similar, but not restricted to exactly two values.
你用过std::pair
吗?您使用的许多地方std::tuple
都是相似的,但不仅限于两个值。
The disadvantages you list for tuples also apply to std::pair, sometimes you want a more expressive type with better names for its members than first
and second
, but sometimes you don't need that. The same applies to tuples.
您为元组列出的缺点也适用于 std::pair,有时您需要一个比first
and更具有表现力的类型,其成员的名称更好second
,但有时您不需要那样。这同样适用于元组。
回答by igorlord
I think there is NO good use for tuples outside of implementation details of some generic library feature.
我认为在某些通用库功能的实现细节之外,元组没有什么用处。
The (possible) saving in typing do not offset the losses in self-documenting properties of the resulting code.
输入中的(可能的)节省不会抵消结果代码的自文档属性的损失。
Substituting tuples for structs that just takes away a meaningful name for a field, replacing the field name with a "number" (just like the ill-conceived concept of an std::pair).
用元组替换结构体,这些结构体只是为字段取了一个有意义的名称,用“数字”替换字段名称(就像构思错误的 std::pair 概念一样)。
Returning multiple values using tuples is much less self-documenting then the alternatives -- returning named types or using named references. Without this self-documenting, it is easy to confuse the order of the returned values, if they are mutually convertible.
使用元组返回多个值比替代方法要少得多的自我记录——返回命名类型或使用命名引用。如果没有这种自我记录,很容易混淆返回值的顺序,如果它们可以相互转换。
回答by Zack Yezek
The real use cases are situations where you have unnameable elements- variadic templates and lambda functions. In both situations you can have unnamed elements with unknown types and thus the only way to store them is a struct with unnamed elements: std::tuple. In every other situation you have a known # of name-able elements with known types and can thus use an ordinary struct, which is the superior answer 99% of the time.
真正的用例是您拥有不可命名元素的情况——可变参数模板和 lambda 函数。在这两种情况下,您都可以拥有未知类型的未命名元素,因此存储它们的唯一方法是具有未命名元素的结构:std::tuple。在所有其他情况下,您都有已知类型的可命名元素的已知数量,因此可以使用普通结构,这是 99% 的最佳答案。
For example, you should NOT use std::tuple to have "multiple returns" from ordinary functions or templates w/ a fixed number of generic inputs. Use a real structure for that. A real object is FAR more "generic" than the std::tuple cookie-cutter, because you can give a real object literally any interface. It will also give you much more type safety and flexibility in public libraries.
例如,您不应该使用 std::tuple 从具有固定数量的通用输入的普通函数或模板中获得“多次返回”。为此使用真实的结构。一个真实的对象比 std::tuple cookie-cutter 更“通用”,因为你可以给一个真实的对象提供任何接口。它还将为您在公共图书馆中提供更多的类型安全性和灵活性。
Just compare these 2 class member functions:
只需比较这两个类成员函数:
std::tuple<double, double, double> GetLocation() const; // x, y, z
GeoCoordinate GetLocation() const;
With a real 'geo coordinate' object I can provide an operator bool() that returns false if the parent object had no location. Via its APIs users could get the x,y,z locations. But here's the big thing- if I decide to make GeoCoordinate 4D by adding a time field in 6 months, current users's code won't break. I cannot do that with the std::tuple version.
使用真正的“地理坐标”对象,我可以提供一个运算符 bool(),如果父对象没有位置,则返回 false。通过其 API,用户可以获得 x、y、z 位置。但重要的是,如果我决定在 6 个月内通过添加时间字段来制作 GeoCoordinate 4D,则当前用户的代码不会中断。我不能用 std::tuple 版本做到这一点。
回答by julio
I cannot comment on mirk's answer, so I'll have to give a separate answer:
我不能评论 mirk 的回答,所以我必须给出一个单独的答案:
I think tuples were added to the standard also to allow for functional style programming. As an example, while code like
我认为元组被添加到标准中也是为了允许函数式编程。例如,虽然代码如下
void my_func(const MyClass& input, MyClass& output1, MyClass& output2, MyClass& output3)
{
// whatever
}
is ubiquitous in traditional C++, because it is the only way to have multiple objects returned by a function, this is an abomination for functional programming. Now you may write
在传统的 C++ 中无处不在,因为它是函数返回多个对象的唯一方式,这对于函数式编程来说是一种厌恶。现在你可以写
tuple<MyClass, MyClass, MyClass> my_func(const MyClass& input)
{
// whatever
return tuple<MyClass, MyClass, MyClass>(output1, output2, output3);
}
Thus having the chance to avoid side effects and mutability, to allow for pipelining, and, at the same time, to preserve the semantic strength of your function.
因此有机会避免副作用和可变性,允许流水线,同时,保持函数的语义强度。
回答by John Zwinck
Interoperation with other programming languages that use tuples, and returning multiple values without having the caller have to understand any extra types. Those are the first two that come to my mind.
与使用元组的其他编程语言互操作,并返回多个值,而调用者不必了解任何额外的类型。这是我想到的前两个。