对集合中的每个元素调用print的通用算法

Generic algorithm for calling print on each element in the collection

本文关键字:print 算法 调用 集合 元素      更新时间:2023-10-16

在编写如下模板函数时:

template<class T> void print(T const & collection)

当循环遍历集合并解引用迭代器时,如果您有vector<int>之类的东西,则一切正常,除非将其更改为vector<int*>。在不重复代码的情况下,处理单个模板函数差异的最佳方法是什么?

我将编写一个单独的模板函数do_print,它委托给一个类模板printer。类模板是一个执行漂亮打印的函数对象,您可以通过在*t上调用漂亮打印版本来部分专门化T*

所以没有复制漂亮的打印代码,并且编写两个轻量级实现类(这些被任何现代编译器优化掉了,所以没有运行时开销)也不太方便。

与SFINAE技巧相比,我更喜欢这种解决方案,因为部分类专门化比函数重载技巧提供了更多的控制(以及更好的错误消息)。这也是Alexandrescu &Sutter编码标准。

顺便说一句,这段代码也适用于T**,因为T*的专门化委托给了T的代码。因此,T**被发送到T*,最后发送到T。实际上,任意级别的间接操作被简化为输出指针所指向的元素。
#include <iostream>
#include <vector>
namespace detail {
template<typename T>
struct printer
{
   void operator()(T const& t) 
   { 
      std::cout << t; // your pretty print code here
   }  
};
template<typename T>
struct printer<T*>
{
   void operator()(T const* t) 
   { 
      printer<T>()(*t); // delegate to printing elements (no duplication of prettty print)
   }
};
}
template<typename T>
void do_print(T const& t)
{
   detail::printer<T>()(t);
}
template<typename C>
void print(C const& collection)
{
   for(auto&& c: collection) 
      do_print(c);
   std::cout << "n";
}
int main()
{
   int a = 1;
   int b = 2;
   auto c = &a;
   auto d = &b;
   std::vector<int> v1 { a, b };
   std::vector<int*> v2 { c, d };
   std::vector<int**> v3 { &c, &d };
   print(v1);
   print(v2);
   print(v3);
}

实时工作空间输出