I am trying to make a header file that makes it easy to learn C . I was wondering if there was any way to make a print function in C that behaved similar to the print function in Python which prints the data irrespective of the datatype or dimensions of the data passed to it.
I could make a function that could print any numeric types and strings using templates and function overloading. But I am struggling with vectors and arrays as they may be multi dimensional.
I could get it to print upto 3D vectors using this:
#include <iostream>
#include <vector>
template<typename T>
void printVector(const std::vector<T>& vec)
{
for (const auto& element : vec)
std::cout << element << ' ';
std::cout << '\n';
}
template<typename T>
void printVector(const std::vector<std::vector<T>>& vec)
{
for (const auto& innerVector : vec)
printVector(innerVector);
}
int main()
{
std::vector<int> vec1{ 1, 2, 3, 4, 5 };
std::vector<std::vector<double>> vec2{ { 1.1, 2.2 }, { 3.3, 4.4 } };
std::vector<std::vector<std::vector<char>>> vec3{ { { 'a', 'b' }, { 'c', 'd' } }, { { 'e', 'f' }, { 'g', 'h' } } };
printVector(vec1);
printVector(vec2);
printVector(vec3);
return 0;
}
CodePudding user response:
You can do something like this:
#include <iostream>
#include <vector>
#include <map>
namespace detail {
template<typename T>
void printImpl(const T& o)
{
std::cout << o;
}
template<typename T>
void printImpl(const std::vector<T>& vec)
{
char sep = '{';
for (const auto& innerVector : vec) {
std::cout << sep;
printImpl(innerVector);
sep = ',';
}
std::cout << "}";
}
template<typename K, typename V>
void printImpl(const std::map<K, V>& cont)
{
char sep = '{';
for (auto&& [k, v] : cont) {
std::cout << sep;
printImpl(k);
std::cout << ":";
printImpl(v);
sep = ',';
}
std::cout << "}";
}
}
template<typename... Args>
void print(Args&&... args)
{
(detail::printImpl(std::forward<Args>(args)), ...);
}
int main()
{
std::vector<int> vec1{ 1, 2, 3, 4, 5 };
std::vector<std::vector<double>> vec2{ { 1.1, 2.2 }, { 3.3, 4.4 } };
std::vector<std::vector<std::vector<char>>> vec3{ { { 'a', 'b' }, { 'c', 'd' } }, { { 'e', 'f' }, { 'g', 'h' } } };
std::map<int, std::string> m{{0, "a"},{1, "b"}};
print(vec1,"\n");
print(vec2,"\n");
print(vec3,"\n");
print(m,"\n");
return 0;
}
And specialize detail::printImpl()
for any type for which you don't like default operator <<()
behavior.