#include <any>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
template<class T>
struct is_vector : std::false_type {};
template<class T>
inline constexpr bool is_vector_v = is_vector<T>::value;
template <typename T>
string VectorToString(const vector<T> &vec)
{
string res = "[";
int n = vec.size();
for (size_t i=0; i<n; i ) {
if constexpr(is_vector_v<T>) res = VectorToString(vec[i]);
else res = std::to_string(vec[i]);
if (i < n-1) res = ", ";
}
res = "]";
return res;
}
int main( int argc, char** argv )
{
vector<int> a = {1,2,3};
cout << VectorToString(a) << "\n";
vector<vector<int>> b = {{1,2,3}, {4,5,6}, {7,8,9}};
//cout << VectorToString(b);
vector<vector<vector<double>>> c = {{{1,2,3}, {4,5,6}}, {{7,8,9}}};
//cout << VectorToString(c);
return 0;
}
I'm trying to make a print function that works with any vector type, like Python.
I wish to use template if possible, but not sure how. What should struct is_vector
looks like to do this?
If a template solution is not possible, then I'd like to see any solution possible.
CodePudding user response:
What should struct
is_vector
looks like to do this?
It looks like what template partial specialization looks like
template<class T>
struct is_vector : std::false_type {};
template<class T, class Alloc>
struct is_vector<std::vector<T, Alloc>> : std::true_type {};
CodePudding user response:
One option is to mix templates and operator overloading as shown below. In particular, to overload operator<<
for a std::vector
. A very crude example is given below. It prints all the elements of a std::vector
.
//this will be selected for 1D std::vector
template<typename T>
std::ostream& operator<<(std::ostream &os, const std::vector<T> &vec)
{
for(auto it = vec.begin(); it!=vec.end(); it)
{
os<< (*it)<<" ";
}
return os;
}
//for arbitrarily nested std::vector
template<typename T>
std::ostream& operator<<(std::ostream &os, const std::vector<std::vector<T>> &vec)
{
for(auto it = vec.begin(); it!=vec.end(); it)
{
os << *it;
}
return os;
}
int main()
{
std::vector<int> vec1{1,2,3};
std::cout<<vec1<<std::endl; //prints 1 2 3
std::vector<std::vector<int>> vec2 = {{1,2,3}, {4,5,6}, {7,8,9}}; //1 2 3 4 5 6 7 8 9
std::cout<<vec2<<std::endl;
std::vector<std::vector<std::vector<double>>> vec3{{{1,2,3}, {4,5,6}, {7,8,9}}, {{-1,-2,-3}, {-4,-5,-6}, {-10,-22,36}}, {{129,212,999}, {0,0,1}, {3,5,4}}};
std::cout<<vec3<<std::endl;
return 0;
}
The output of the above program is:
1 2 3
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 -1 -2 -3 -4 -5 -6 -10 -22 36 129 212 999 0 0 1 3 5 4
Demo.
Another option would be to use fold expressions for the same.