使用一个函数打印map和unordered_map对

时间:2016-11-15 12:03:21

标签: c++ c++11 templates

我已经有了这个有效的代码:

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream &out, std::map<T1, T2> &map){
        for (auto it = map.begin(); it != map.end(); ++it) {
                out <<  it-> first << ", " << it->second << '\n';
        }
        return out;
}
template <typename T1, typename T2>
std::ostream& operator<<(std::ostream &out, std::unordered_map<T1, T2> &map){
        for (auto it = map.begin(); it != map.end(); ++it) {
                out <<  it-> first << ", " << it->second << '\n';
        }
        return out;
}

正如您所看到的,两个功能几乎完全相同。有没有办法删除一个并只使用一个抽象函数?

2 个答案:

答案 0 :(得分:3)

您确实可以:这里是任何可迭代类型的单一函数模板,其value_typestd::pair<>。这不仅适用于std::map<>std::unordered_map<>,还适用于std::vector<std::pair<>>boost::container::list<std::pair<>>等:

namespace detail {
    template<typename>
    struct is_pair : std::false_type { };

    template<typename T1, typename T2>
    struct is_pair<std::pair<T1, T2>> : std::true_type { };
}

template<
    // collection type
    typename T,
    // ensure value_type exists
    typename VT = typename T::value_type,
    // ensure value_type is some std::pair<>
    typename std::enable_if<detail::is_pair<VT>{}>::type* = nullptr
>
auto operator <<(std::ostream& out, T const& coll)
// ensure begin(coll) and end(coll) are legal
-> decltype(void(begin(coll)), void(end(coll)), out) {
    for (auto it = begin(coll); it != end(coll); ++it) {
        out << it->first << ", " << it->second << '\n';
    }
    return out;
}

Online Demo

答案 1 :(得分:0)

这是一个示范程序

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring-boot-fundamentals</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.1.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.7</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-legacy</artifactId>
            <version>1.0.2.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <packaging>war</packaging>
</project>

它的输出是

#include <iostream>
#include <map>
#include <type_traits>
#include <utility>

template <class T1, class T2, class T3, class T4,
          template <class T1, class T2, class T3, class T4> class Container>

std::ostream & operator<<( std::ostream &out, const Container<T1, T2, T3, T4> &c )
{
    static_assert( ( std::is_same<typename Container<T1, T2, T3, T4>::value_type, 
                     std::pair<const T1, T2>>::value ), "Invalid value type of the Container" );
    for ( const auto &p : c ) 
    {
        out <<  p.first << ", " << p.second << '\n';
    }

    return out;
}


int main() 
{
    std::map<int, char> m = 
    {
        { 65, 'A' }, { 66, 'B' }, { 67, 'C' }
    };

    std::cout << m << std::endl;

    std::multimap<int, char> mm = 
    {
        { 65, 'A' }, { 66, 'B' }, { 67, 'C' }
    };

    std::cout << mm << std::endl;

    return 0;
}