質問

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 << "]";
}

他のヒント

Perhaps you should follow the pattern of the for_each algorithm. Follow the link for an example of how that algorithm can be defined. http://www.cplusplus.com/reference/algorithm/for_each/

If you want a printer that is generic then you should prefer using iterators as inputs to the algorithm. Then it makes no difference which container supplies them, and your function could even take pointers to C arrays. Take that further, and if you want it to work for user defined types, then user defined types should have overloaded stream operators to support them.

Take a look at this as well, and consider even more options. http://www.cplusplus.com/reference/iterator/ostream_iterator/

I couldn't post this in a comment, but here is a simplified version of the other answer with a main for testing. It was tested at http://www.compileonline.com/compile_cpp11_online.php

Of course you might need specializations for other types such as double or user defined types.

#include <vector>
#include <list>
#include <iostream>

template <typename T>
void print_container(const T&);

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

template <typename T>
void print_container(const T& c) {
    std::cout << "[";
    bool isFirst = true;
    for (const auto& e : c) {
        if (isFirst) isFirst = false;
        else std::cout << ",";
        print(e);
    }
    std::cout << "]";
}

int main()
{
    std::vector<int> v = {0, 1, 3, 5, 7, 9};
    std::list<int> l =  {0, 1, 3, 5, 7, 9};

    print_container(v); 
    print_container(l);
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top