【问题标题】:Printing map and unordered_map pairs with one function使用一个功能打印 map 和 unordered_map 对
【发布时间】:2016-11-15 12:03:21
【问题描述】:

我已经有了这个工作代码:

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

如您所见,这两个功能几乎相同。有没有办法去掉一个而只使用一个抽象函数?

【问题讨论】:

  • 编写第三个模板,它只接受一个通用的typename T 参数,并从这两个参数中调用它。

标签: c++ c++11 templates


【解决方案1】:

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

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

【讨论】:

  • 您能多解释一下解决方案吗?您能否指出一些好的资源来更好地理解 C++ 模板?
  • @dv1729 :您需要缩小您的请求范围并阐明您需要解释的方面。 SFINAE 是这里使用的唯一技术,SO 上有几十个质量答案深入解释了 SFINAE; this 可能是一个很好的起点(虽然它看起来有点过时)。
【解决方案2】:

这是一个演示程序

#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;
}

它的输出是

65, A
66, B
67, C

65, A
66, B
67, C

【讨论】:

    猜你喜欢
    • 2018-09-17
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多