I'm trying to write a function which I can call whenever I need to print something. However, when printing a vector or list I need it to behave slightly differently. Also, a vector or list can contain another vector or list.
My first approach was to do something like this:
#include <iostream>
#include <list>
#include <vector>
using namespace std;
template <typename T>
void
print(const vector<T>& v) {
cout << "[";
bool isFirst = true;
for (const T& e : v) {
if (isFirst) isFirst = false;
else cout << ",";
print(e);
}
cout << "]";
}
template <typename T>
void
print(const list<T>& l) {
cout << "[";
bool isFirst = true;
for (const T& e : l) {
if (isFirst) isFirst = false;
else cout << ",";
print(e);
}
cout << "]";
}
template <typename T>
void
print(const T& v) {
cout << v;
}
int
main(int argc, char** argv) {
vector<int> v;
print(v);
return 0;
}
As you see, there is a lot of code duplication for printing vectors and lists, but I don't know how to combine these. In any case, the code doesn't compile as the compiler tries to match printing of a scalar entity (such as int
) with the first implementation of print
instead of the last implementation:
g++ -std=c++11 test.cpp
test.cpp: In instantiation of ‘void print(const std::vector<T>&) [with T = int]’:
test.cpp:42:12: required from here
test.cpp:15:16: error: no matching function for call to ‘print(const int&)’
print(e);
^
test.cpp:15:16: note: candidate is:
test.cpp:9:1: note: template<class T> void print(const std::vector<T>&)
print(const vector<T>& v) {
^
test.cpp:9:1: note: template argument deduction/substitution failed:
test.cpp:15:16: note: mismatched types ‘const std::vector<T>’ and ‘const int’
print(e);
^
Any idea of how I can solve this?
There are many neat solutions, but one that is quite close to yours without duplication, without anything too smart and without any library function is the following
template <typename T>
void print_container(const T&);
template <typename T>
void print(const std::vector<T>& v) { print_container(v); }
template <typename T>
void print(const std::list<T>& l) { print_container(l); }
template <typename T>
void print(const T& e) { cout << e; }
template <typename T>
void print_container(const T& c) {
cout << "[";
bool isFirst = true;
for (const auto& e : c) {
if (isFirst) isFirst = false;
else cout << ",";
print(e);
}
cout << "]";
}