简体   繁体   中英

how to handle arbitrary dimensional vector in c++?

I want to create a function that can handle arbitrary dimensional vector, function in psudocode:

template<class T>
void printVector(vector<T> t){
    if(T==vector){
        printf("[");
        for(auto it=t.begin(),it!=t.end();++it){
            printVector(*it);
        }
        printf("]");
    }else{
        printf("%d ",t);
    }
}

for example:

vector<int> a;
a.push_back(12);
a.push_back(34);

printVector(a);

the output should be [12 34],

vector<vector<int> > b;
vector<int> b1;
b1.push_back(1);
b1.push_back(2);
b.push_back(b1);

vector<int> b2;
b2.push_back(3);
b2.push_back(4);
b.push_back(b2);

printVector(b);

the output should be [[1 2][3 4]]

The C++ template system supports recursion. You had the right idea, but you need to overload the function:

void printVector(int t) {
    printf("%d ", t);
}

template<class T>
void printVector(std::vector<T> t) {
    printf("[");
    for(auto v : t){
        printVector(v);
    }
    printf("]");
}

The first function handles the base case. The recursive case is handled by the second function, and it should be easy to understand.

For your second example, the one that outputs [[1 2 ][3 4 ]] , the compiler ends up generating printVector<vector<vector<int> > >() , printVector<vector<int> >() , and it uses the leaf printVector(int) .

Of course you should give this function a better name.

Since the question is marked as C++, why no take a C++ approach?

template <template <typename ...> class CONTAINER, typename ... ARGS>
std::ostream &operator <<(std::ostream &o, const CONTAINER<ARGS ...> &container)
{
    o << '[';
    for (const auto &item : container)
    {
        o << item << ' ';
    }
    o << ']';

    return o;
}

This operator will handle any template and try to pass it to the ostream::operator << , so it could be valid for any kind of container which contained type is supported by the ostream::operator << .

If we define also a free ostream::operator << to handle std::pairs it can be used also for std::map :

template <typename F, typename S>
std::ostream &operator <<(std::ostream &o, const std::pair<F, S> &pair)
{
    return o << pair.first << ':' << pair.second;
}

I've tried it with std::vector<int> , std::vector<std::vector<int>> , std::vector<std::vector<std::vector<int>>> and the same for std::valarray and std::set ; also with a std::map .

Beware! is ambiguous used with std::string ! So it shouldn't be used in a scope where strings are printed or we should look for a way to disable the template for std::string .


Edit

The function approach suggested by Adam is also applicable to my approach and it doesn't collide with the std::string printing of std::ostream :

template <typename T>
void printContainer(const T &value)
{
    std::cout << value;
}

template <template <typename ...> class CONTAINER, typename ... ARGS>
void printContainer(const CONTAINER<ARGS ...> &container)
{
    std::cout << '[';
    for (const auto &item : container)
    {
        printContainer(item);
        std::cout << ' ';
    }
    std::cout << ']';
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM