相当印刷元组的解剖学

时间:2014-12-02 15:16:17

标签: c++ c++11 tuples variadic-templates pretty-print

不久前,打印出std :: tuple的解决方案已发布here。在大多数情况下,我得到了正在发生的事情。我很难理解print_tuple函数中发生的事情。

template<class Ch, class Tr, class Tuple, std::size_t... Is>
void print_tuple(std::basic_ostream<Ch,Tr>& os, Tuple const& t, seq<Is...>){
  using swallow = int[];
  (void)swallow{0, (void(os << (Is == 0? "" : ", ") << std::get<Is>(t)), 0)...};
}

我不知道这个功能正在发生什么。据我所知,它与解包Is有关。我明白了条件,Is == 0正在检查我们是否在头部元素。

那是怎么回事?

2 个答案:

答案 0 :(得分:8)

让我们来看一个带有任意元组的例子,比如说:

using Tuple = tuple<char, int, string>;

因此,我们的函数将被调用的整数序列是:

seq<0, 1, 2>

我们的身体包装扩展是:

(void)swallow{0, (void(os << (Is == 0? "" : ", ") << std::get<Is>(t)), 0)...};

,如果我们按照编译器的方式手动扩展它,那么:

(void)swallow{0,
              (void(os << (0 == 0? "" : ", ") << std::get<0>(t)), 0),
              (void(os << (1 == 0? "" : ", ") << std::get<1>(t)), 0),
              (void(os << (2 == 0? "" : ", ") << std::get<2>(t)), 0)
              };

然后评估分支机构:

(void)swallow{0,
              (void(os << "" << std::get<0>(t)), 0),
              (void(os << ", " << std::get<1>(t)), 0),
              (void(os << ", " << std::get<2>(t)), 0)
              };

也就是说,我们正在构造一个4 0 s的整数数组,副作用是打印出元组的内容,以逗号分隔,确保我们不会以额外的逗号。必须按顺序评估四个表达式 ,以确保按顺序打印元组内容。

初始(void)强制转换就是为了避免编译器在打开所有警告时应该发出的未使用变量警告。数组初始化中的初始0处理元组为空的情况。

答案 1 :(得分:0)

(os << (Is == 0? "" : ", ") << std::get<Is>(t))打印Is元素(", "的前缀为Is > 0

然后,将结果转换为void以避免逗号运算符可能过载。

(/*previous stuff*/, 0)...执行一系列0

{0, /*previous stuff*/ }管理sizeof...(Is) == 0

的案例

swallow /*previous stuff*/构建一个0数组。

void /*previous stuff*/:施展无效以避免警告。