专用于容器等地图的功能

Siv*_*ran 7 c++ c++11

我想专门为vector和map映射容器的函数模板.对于矢量我可以像下面这样做,但我不知道我怎么能有一个专门版本的功能,只用于地图像容器.

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

using namespace std;

template<typename Iterator>
void print(Iterator begin, Iterator end)
{
    while (begin != end)
    {
        cout << *begin << endl; // compiler error for map like containers
        ++begin;
    }
}

int main()
{
    vector<int> noVec = { 1, 2, 3 };

    print(noVec.begin(), noVec.end());

    map<int, int> nosMap;
    nosMap[0] = 1;
    nosMap[1] = 2;
    nosMap[3] = 3;

    print(nosMap.begin(), nosMap.end());

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这个问题是类似的,但它建议在向量中使用对,我不想这样做.我知道专业化可以通过SFINAE完成,但不知道要检查的条件.如果我能用C++ 11 type_traits实现这一目标会很棒.

Mad*_*ist 9

value_typemap是一些对,所以你可以检查value_type迭代器的是std::pair或不是,如

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

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

template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type 
{ };



template <typename Iter>
typename std::enable_if<is_pair<typename std::iterator_traits<Iter>::value_type>::value>::type
print(Iter begin, Iter end)
{
  std::cout << "called with map-like" << std::endl;
  for (; begin != end; ++begin)
  {
    std::cout << begin->second;
  }
  std::cout << std::endl;
}

template <typename Iter>
typename std::enable_if<!is_pair<typename std::iterator_traits<Iter>::value_type>::value>::type
print(Iter begin, Iter end)
{
  std::cout << "called with vector-like" << std::endl;
  for (; begin != end; ++begin)
  {
    std::cout << *begin;
  }
  std::cout << std::endl;
}



int main()
{
  std::vector<int> vec { 1, 2, 3 };
  std::map<int, int> map {{0, 0}, {1, 1}, {2, 4}, {3, 9}};

  print(vec.begin(), vec.end());
  print(map.begin(), map.end());
}
Run Code Online (Sandbox Code Playgroud)

打印

called with vector-like
123
called with map-like
0149
Run Code Online (Sandbox Code Playgroud)

  • 我不明白的是"typename std :: iterator_traits <Iter> :: value_type"如何转换为is_pair(true_type)的两个模板参数.是否有任何链接可以帮助我理解? (2认同)

101*_*010 5

你不需要专门化任何东西.所有您需要做的是提供一个重载输出operator<<std::pair,如下面的例子:

template<typename T1, typename T2>
std::ostream& operator<<(std::ostream &out, std::pair<T1, T2> const &mp) {
  return (out << "(" << mp.first << ", " << mp.second << ")");
}
Run Code Online (Sandbox Code Playgroud)

现场演示


编辑:

然而,由于上述方案@Benjamin林德利的意见建议可能与输出的其他模板重载冲突operator<<std::pair.

如果是这种情况,或者您可以在自己的命名空间中编写(例如namespace detail)两个模板函数重载(例如print_elem),如下例所示:

namespace detail {
  template<typename T1, typename T2>
  std::ostream& print_elem(std::ostream &out, std::pair<T1, T2> const &mp) {
    return (out << "(" << mp.first << ", " << mp.second << ")");
  }

  template<typename T>
  std::ostream& print_elem(std::ostream &out, T const &elem) {
      return (out << elem);
  }
}
Run Code Online (Sandbox Code Playgroud)

并改变你template print喜欢的例子如下:

template<typename Iterator>
void print(Iterator begin, Iterator end)
{
    while (begin != end) {
        detail::print_elem(cout, *begin) << endl;
        ++begin;
    }
}
Run Code Online (Sandbox Code Playgroud)

现场演示