When writing a template function like:
template<class T> void print(T const & collection)
When looping through the collection and dereferencing the iterator everything works right if you have something like vector<int>
unless you change it to vector<int*>
. What's the best way to deal with the differences in a single template function whilst not duplicating code?
I would write a single template function do_print
that delegates to a class template printer
. The class template is a function object that does the pretty printing, and that you partially specialize for T*
by simply calling the pretty print version on *t
.
So there is no duplication of the pretty printing code and a minor inconvenience for writing two lightweight implementation classes (these get optimized away by any modern compiler, so there is no runtime overhead).
I prefer this solution over SFINAE tricks because partial class specialization gives you much more control (and much better error messages) than function overloading tricks. It's also recommended by the Alexandrescu & Sutter Coding Standards.
BTW, this code will also work for T**
because the specialization for T*
delegates to the code for T
. So T**
is send to T*
and finally to T
. In fact, arbitrary levels of indirection get reduced to printing the elements pointed to by pointers.
#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);
}
Output on Live Work Space