我想专门为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实现这一目标会很棒.
该value_type的map是一些对,所以你可以检查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)
你不需要专门化任何东西.所有您需要做的是提供一个重载输出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)