编写模板函数时,例如:
template<class T> void print(T const & collection)
当循环遍历集合并取消引用迭代器时,如果你有类似的东西,一切都会正常工作,vector<int>
除非你将它更改为vector<int*>
. 在不复制代码的情况下处理单个模板函数中的差异的最佳方法是什么?
编写模板函数时,例如:
template<class T> void print(T const & collection)
当循环遍历集合并取消引用迭代器时,如果你有类似的东西,一切都会正常工作,vector<int>
除非你将它更改为vector<int*>
. 在不复制代码的情况下处理单个模板函数中的差异的最佳方法是什么?
do_print
我会编写一个委托给类模板的单个模板函数printer
。类模板是一个执行漂亮打印的函数对象,您T*
只需在*t
.
所以没有重复漂亮的打印代码,并且编写两个轻量级实现类也有一点不便(这些都被任何现代编译器优化掉了,所以没有运行时开销)。
与 SFINAE 技巧相比,我更喜欢这种解决方案,因为与函数重载技巧相比,部分类专业化为您提供了更多的控制(以及更好的错误消息)。Alexandrescu & Sutter 编码标准也推荐它。
T**
顺便说一句,此代码也适用T*
于T
. T**
send toT*
和 finally to也是如此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);
}
实时工作空间上的输出