在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>
,这是一个更短的声明,方便的构造函数和运算符已经预定义,但具有以下缺点:
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)
LB-*_*B-- 20
我认为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);
}
Run Code Online (Sandbox Code Playgroud)
以及答案中的许多其他示例.我发现这个例子是最常用的,因为它比以前在C++ 03中节省了很多精力.
Jon*_*ely 13
你用过std::pair
吗?您使用的许多地方std::tuple
都很相似,但不限于两个值.
您列出的元组的缺点也适用于标准::对,有时候你想要一个更具表现力与类型为会员优于名称first
和second
,但有时你并不需要这一点.这同样适用于元组.
igo*_*ord 11
我认为除了一些通用库特性的实现细节之外,元组没有很好用.
键入的(可能的)节省不会抵消结果代码的自记录属性的损失.
将元组替换为仅占用字段的有意义名称的结构,将字段名称替换为"数字"(就像std :: pair的错误概念一样).
使用元组返回多个值远不如自我文档那么替代 - 返回命名类型或使用命名引用.如果没有这种自我记录,如果它们是可相互转换的,则很容易混淆返回值的顺序.
小智 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版本做到这一点.