如何在c ++中打印通用地图

时间:2015-04-30 07:42:17

标签: c++ templates

我想写一个打印通用地图的功能。 这就是我到目前为止所做的:

    template<typename map_key, typename map_val>
    void log(DEBUG_LEVEL level, std::map<map_key, map_val> _map) {
        if (level >= d_level) {
            for (std::map<map_key, map_val>::iterator it = _map.begin();
                    it != _map.end(); ++it)
                std::cout << it->first << " => " << it->second << '\n';
        }
    }

它无法编译。

error: expected ';' before 'it'
error: 'it' was not declared in this scope
  1. 为什么这不是编译?
  2. 有更好的方法来写这个吗?我找到一个衬垫来打印矢量here(第二个答案),我想知道地图是否有相同的内容?
  3. 更新:我修复了(1)但仍在等待(2)的答案 我喜欢Galik的答案,但是当我尝试将其添加为函数时,我收到了一个错误:error:'std::ostream& Logger::operator<<(std::ostream&, const std::pair<const _Key, _Tp>&)' must take exactly one argument

    这是我的Logger类:

    extern DEBUG_LEVEL d_level;
    
    class Logger {
    
    public:
    
        Logger(const char * app_name);
        Logger(DEBUG_LEVEL level, char * app_name);
        void log(DEBUG_LEVEL level, const char* str, ...);
    
        template<typename vector_type>
        void log(DEBUG_LEVEL level, const std::vector<vector_type>& _vec,
                const std::string seperator = ", ") {
            if (level >= d_level) {
                std::cout << get_prefix_msg() << " ";
                change_color(level);
                std::cout << "[";
                std::copy(_vec.begin(), _vec.end(),
                        std::ostream_iterator<vector_type>(std::cout,
                                seperator.c_str()));
                std::cout << "]\n";
                printf(ANSI_COLOR_RESET);
            }
        }
    
        template<typename map_key, typename map_val>
        void log(DEBUG_LEVEL level, const std::map<map_key, map_val>& _map,
                const std::string seperator = ", ") {
            if (level >= d_level) {
                std::cout << get_prefix_msg() << " \n";
                change_color(level);
                std::cout << "[";
                for (typename std::map<map_key, map_val>::const_iterator it =
                        _map.begin(); it != _map.end(); ++it)
                    std::cout << it->first << " => " << it->second << seperator;
                std::cout << "]\n";
                printf(ANSI_COLOR_RESET);
            }
        }
    
        /**
         * will log but without the application _app_name and without the debug level (but will have the right color)
         */
        void strip_log(DEBUG_LEVEL level, const char* str, ...);
    
        void change_verbosity(DEBUG_LEVEL level);
    
        static int msg_id;
    private:
        const char * _app_name;
        void change_color(DEBUG_LEVEL level, bool is_strip = false);
        int get_next_msg_id();
        std::string get_prefix_msg();
        static DEBUG_LEVEL d_level;
    
    };
    

2 个答案:

答案 0 :(得分:4)

缺少

typename。 它应该是

template<typename map_key, typename map_val>
void log(DEBUG_LEVEL level, const std::map<map_key, map_val>& _map) {
    if (level >= d_level) {
        for (typename std::map<map_key, map_val>::const_iterator it = _map.begin(); it != _map.end(); ++it)
            std::cout << it->first << " => " << it->second << '\n';
    }
}

或在C ++ 11中

template<typename map_key, typename map_val>
void log(DEBUG_LEVEL level, const std::map<map_key, map_val>& _map) {
    if (level >= d_level) {
        for (const auto& p : _map)
            std::cout << p.first << " => " << p.second << '\n';
    }
}

答案 1 :(得分:3)

在回答第二个问题时,您可能会考虑更加通用并允许更多不同类型的容器。

类似的东西:

#include <map>
#include <set>
#include <vector>
#include <iostream>

typedef int DEBUG_LEVEL;
int d_level = 0;

template<typename Key, typename Value>
std::ostream& operator<<(std::ostream& os, const std::pair<const Key, Value>& p)
{
    os << p.first << " => " << p.second;
    return os;
}

template<typename Container>
void log(DEBUG_LEVEL level, const Container& c) {
    if (level >= d_level) {
        for(typename Container::const_iterator it = c.begin();
            it != c.end(); ++it)
        std::cout << *it << '\n';
    }
}

// OPTIONAL Adding your own types

class MyClass
{
    int i;
    std::string s;
public:
    MyClass(int i, std::string s): i(i), s(s) {}

    // declare the operator<<() overload as a friend to grant access
    // to private members
    friend std::ostream& operator<<(std::ostream& os, const MyClass& mc);

};

// define the operator<<() for MyClass as a global function (required)
std::ostream& operator<<(std::ostream& os, const MyClass& mc)
{
    os << "{MyClass: " << mc.s << ": " << mc.i << "}";
    return os;
}


// End of OPTIONAL

int main()
{
    std::set<int> s;
    s.insert(6);
    s.insert(3);
    s.insert(4);

    std::map<int, int> m;// {{1, 2}, {3, 4}};
    m[1] = 2;
    m[3] = 4;

    std::vector<int> v;
    v.push_back(4);
    v.push_back(3);
    v.push_back(2);
    v.push_back(1);

    std::cout << "\nset:\n";
    log(1, s);

    std::cout << "\nmap:\n";
    log(1, m);

    std::cout << "\nvector:\n";
    log(1, v);

    std::cout << "\nvector of MyClass:\n";
    std::vector<MyClass> vmc;
    vmc.push_back(MyClass(1, "hello"));
    vmc.push_back(MyClass(2, "world"));

    log(1, vmc);
}

<强>输出:

set:
3
4
6

map:
1 => 2
3 => 4

vector:
4
3
2
1

vector of MyClass:
{MyClass: hello: 1}
{MyClass: world: 2}