C++ 在C++;11?

C++ 在C++;11?,c++,c++11,tuples,C++,C++11,Tuples,在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) :

在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
int a;
int b;
std::tie(a,b)=fun();
模板
void mwquicksort(T*pT、int-nitem、const-int-M、CmpF-cmp、LessF-less)
{
结构SI
{
int l,r,w;
SI(){}
SI(int _l,int _r,int _w):l(_l),r(_r),w(_w){
}堆栈[40];
//等
我正在考虑用
std::tuple
替换
SI
结构,这是一个更短的声明,已经预定义了方便的构造函数和运算符,但有以下缺点:

  • 元组元素隐藏在模糊的、实现定义的结构中。即使VisualStudio很好地解释和显示了它们的内容,我仍然不能放置依赖于元组元素值的条件断点
  • 访问单个元组字段(
    get(some_tuple)
    )比访问结构元素(
    s.l
    )要详细得多
  • 按名称访问字段比按数字索引访问字段信息量大得多(也短得多!)
最后两点在某种程度上由
tie
函数解决。考虑到这些缺点,什么是元组的好用例


更新结果表明,VS2010 SP1调试器无法显示以下数组的内容
std::tuple stack[40]
,但在使用结构进行编码时,它可以正常工作。因此,这一决定基本上是不需要动脑筋的:如果您需要检查其值,请使用结构[特别是对于GDB这样的调试器非常重要]

std::tuple<int,int> fun();

嗯,依我看,最重要的部分是泛型代码。编写适用于所有类型结构的泛型代码要比编写适用于元组的泛型代码困难得多。例如,您提到的函数几乎不可能用于结构

这允许您执行以下操作:

  • 存储延迟执行的功能参数(例如)
  • 返回多个参数,无需使用
    std::tie
  • 组合(不是等类型的)数据集(例如,从并行执行),可以像
    std::tuple\u cat
    那样简单地完成

问题是,它并不仅仅限于这些用途,人们可以在此列表上进行扩展,并基于元组编写通用功能,而元组对于结构来说要困难得多。谁知道呢,也许明天有人会在序列化方面找到一个很好的用途。

你曾经使用过
std::pair
吗?很多你会使用
std::tupl>的地方e
类似,但不限于两个值


您为元组列出的缺点也适用于std::pair,有时您希望其成员具有比
first
second
更好的名称的更具表现力的类型,但有时您不需要它。元组也是如此。

我认为,除了一些泛型的实现细节之外,元组没有什么好的用途库功能

键入中的(可能)保存不会抵消生成代码的自文档属性的损失

用元组替换结构,只会删除字段的有意义的名称,用“数字”替换字段名称(就像std::pair的错误概念一样)


使用元组返回多个值比使用其他方法(返回命名类型或使用命名引用)更不需要自我记录。没有这种自我记录,如果返回值可以相互转换,则很容易混淆返回值的顺序。

我认为元组的大多数用法来自
std::tie

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

bool MyStruct::operator真正的用例是有不可测量元素的情况——可变模板和lambda函数。在这两种情况下,都可以有未知类型的未命名元素,因此存储它们的唯一方法是有未命名元素的结构:std::tuple。在其他任何情况下,都有一个已知的名称able元素具有已知类型,因此可以使用普通结构,这在99%的情况下是最好的答案

例如,您不应该使用std::tuple从普通函数或模板中获得“多个返回”,而这些函数或模板具有固定数量的通用输入。为此,请使用实际结构。实际对象更为“通用”比std::tuple cookie cutter更重要,因为您可以在任何界面上提供真实对象。它还将在公共库中为您提供更大的类型安全性和灵活性。

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

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

GeoCoordinate  GetLocation() const;
std::tuple GetLocation()const;//x,y,z
地理坐标GetLocation()常量;

使用真实的“地理坐标”对象,我可以提供运算符bool()如果父对象没有位置,则返回false。通过其API,用户可以获得x、y、z位置。但重要的是,如果我决定在6个月内通过添加一个时间域来制作GeoCoordinate 4D,当前用户的代码将不会中断。我无法使用std::tuple版本来完成此操作。

我无法对mirk的答案发表评论,因此我必须给出答案另一个答案是:

我认为在标准中添加元组也是为了允许函数式编程

void my_func(const MyClass& input, MyClass& output1, MyClass& output2, MyClass& output3)
{
   // whatever
}

在传统C++中无处不在,因为它是一个函数返回多个对象的唯一方法,这是函数编程的一个讨厌的问题。现在你可以写< /P>

tuple<MyClass, MyClass, MyClass> my_func(const MyClass& input)
{
   // whatever
   return tuple<MyClass, MyClass, MyClass>(output1, output2, output3);
}
tuple my_func(const MyClass&input)
{
//随便
返回元组(output1、output2、output3);
}
因此有机会避免副作用和易变性,允许管道化,同时保留您的语义强度