【问题标题】:usage c++11 std::tuple in big projects [closed]在大型项目中使用 c++11 std::tuple [关闭]
【发布时间】:2014-02-15 16:05:10
【问题描述】:

C++11 添加了非常有用的容器 std::tuple,现在我可以将许多结构转换为 std::tuple :

// my Field class
struct Field 
{
     std::string path;
     std::string name;
     int id;
     int parent_id;
     int remote_id;    
};

//create
Field field = {"C:/", "file.txt", 23, 20, 41 };  

 //usage
  foo( field.path );
  field.name= new_name;
  int id = field.id;

//to std::tuple,               /--path,  /--name      /--id, /--parend_id,   /--remote_id
using Field = std::tuple< std::string, std::string , int,   int ,           int >;

//create
auto field = make_tuple<Field>("C:\", "file.txt", 23, 20, 41);      



// usage
     foo( std::get<0>(field) );  // may easy forget that the 0-index is path
     std::get<1>(field) = new_name; // and  1-index is name
     int id = std::get<2>(field);   // and 2-index is id, also if I replace it to 3, 
                       //I give `parent_id` instead of `id`, but compiler nothing say about.

但是,这只是在大型项目中使用 std::tuple 的一个缺点 - 可能很容易忘记每种元组的含义,因为这里不是按名称访问,只能按索引访问。

因此,我会使用旧的 Field 类。

我的问题是,我能简单又漂亮地解决这个缺点吗?

【问题讨论】:

  • 您可以使用enum 类型来指定索引并使内容更具可读性。
  • 这正是您应该在这种情况下使用元组的原因!
  • 你解决了什么问题/使用 tuples 代替结构有什么好处?
  • 是的,你可以很好地解决这个问题overloading the dot operator。简单!
  • 请不要使用这样的元组。

标签: c++ c++11 tuples stdtuple


【解决方案1】:

是的,你可以简单漂亮地解决缺点:

为工作使用正确的工具!在这种情况下,结构或类。

元组并不意味着在这种情况下替换结构。仅仅因为您的工具箱中有一把新的闪亮的锤子并不意味着您现在就应该用它来砍木头。

【讨论】:

  • 对于那些认为“std::get(field)”不像“Field.path”那么容易阅读的人:元组很容易像普通旧的那样容易阅读struct: 你只需要这样定义你的结构 struct Field { std::string $0;标准::字符串 $1;整数 2 美元;整数 3 美元;诠释 $4; };这样一来,所有内容都将很容易阅读。
【解决方案2】:

嗯,从概念上讲 tuple 和普通的旧 struct 非常相似。主要区别在于struct 的成员使用名称访问,而tuple 的成员使用索引访问。

看来您想使用 tuple 作为结构 - 为什么不直接使用 struct

【讨论】:

  • 因为 std::tuple 是标准容器,并且在它之上我可以做比结构体更多的操作,比如 std::make_tuple、std::tuple_cat、std::forward_as_tuple 等等。另外,我可以迭代可变参数函数中的索引字段,从不构造。
  • 单字可以说,std::tuple 对于编译时操作非常有用。它唯一的一个缺点是它的成员不能通过名称访问。
  • 你提到的大部分事情你已经可以用结构和类来做。 make_tuple 只是你的结构的外部构造函数的 make 习惯用法,它永远存在。如果你知道你的结构(你为什么不知道?)my_struct_cat 是微不足道的。
【解决方案3】:

您可以使用枚举来提供“字段名称”:

enum FIELDS { path, name, id, parent_id, remote_id };
auto field = make_tuple<Field>("C:\", "file.txt", 23, 20, 41);      

foo( std::get<FIELDS::path>(field) );  // may easy forget that the 0-index is path
std::get<FIELDS::name>(field) = new_name; // and  1-index is name
int id = std::get<FIELDS::id>(field);  

(编辑后,我在这里为枚举使用限定版本,因为它们是相当常见的字段名称,但并非绝对必要)

【讨论】:

  • 你为什么要使用这些毫无意义的名字呢?为什么不使用FieldPathFieldNameFieldID 等名称?
  • 当然可以,但是我不知道您的字段的语义是什么...显然您应该使用符合您的目的的字段名称。
  • 我只是重复使用了问题中的相同名称...我不明白如果已经给出了新名称,您为什么要发明新名称;)
  • 哦,好吧,我不记得看到最初的结构。将编辑
  • 请不要这样做。你几乎只是用更糟糕的语法重新发明了结构,没有任何优势。
【解决方案4】:

一般来说,您应该只将tuple 用于将在几行内相互包装和使用的数据,或者当您实际上不知道数据是什么时,除了需要将它们打包在一起.有时两者兼而有之。

这使得它对于泛型编程非常有用,例如,你想要打包一些参数并在以后解包它们。或者,如果您有一个本地 lambda,您想从中获得子结果并且不想为它创建一个结构 - 但即便如此,我也会被结构所吸引。

tuple 的一个很好的用途是让您的struct 通过make_tie 方法(和const 版本)返回其参数的std::tie(引用的tuple)。 tuple 为您编写诸如词汇 operator&lt; 之类的东西,这会导致 &lt;== 甚至 = 在某些情况下(默认相等不太正确,但您想要调用默认相等作为子问题)。

【讨论】:

    猜你喜欢
    • 2012-05-23
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-15
    • 2014-10-02
    相关资源
    最近更新 更多