漂亮印刷元组的解剖学
Anatomy of pretty print tuple
不久前,这里发布了打印std::tuple的解决方案。在大多数情况下,我明白发生了什么。不过,我无法理解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
正在检查我们是否处于头部元素。
这到底是怎么回事呢?
让我们通过一个带有任意元组的示例,例如:
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
处理元组为空的情况。
(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
的 int 数组。
void /*previous stuff*/
:投掷至空化以避免警告。
相关文章:
- C++:TypeDef使用元组
- Pybind11:将元组列表从Python传递到C++
- 重载元组索引运算符-C++
- 在C++中,如何通过几种类型从元组中选择多个元素
- 将fold表达式与std::一起用于两个元组
- std::ranges::elements_view,用于自定义类似元组的数据
- 将元组的向量转换/构造为堆
- 专用于 std 元组的模板,而无需用户执行remove_cvref
- 将元组的向量构造成堆
- 元组由 Swig 生成的 Python 包装器返回,用于C++向量
- 将元组类型扩展为可变参数模板?
- 时间复杂度 当具有复合数据类型(如元组或对)时?
- 类内部和外部静态 constexpr 元组之间的差异
- 可变参数模板与使用元组在参数中添加不同的数据对
- 访问和打印元组中的数据,并使用 C++14 使用模板函数显示数据
- boost::包含提升单元的元组的哈希值
- 我正在寻找一种优雅的方式来从元组向量创建tuple_element向量
- 如何在可变参数模板函数中遍历可变参数元组?
- 如何使用 SML 随机生成八进制元组
- 漂亮印刷元组的解剖学