我想专门设计一个矢量函数模板,并像容器一样映射。对于矢量我可以在下面做,但我不知道如何才能有一个专门用于地图集合的函数版本。
#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;
}
This问题类似,但它建议在向量中使用对,我不想做。我知道专业化可以通过SFINAE完成,但不知道要检查的条件。如果我能用C ++ 11 type_traits实现这一点,那就太棒了。
答案 0 :(得分:9)
value_type
的{{1}}是一对,因此您可以检查迭代器的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());
}
答案 1 :(得分: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 << ")");
}
编辑:
但是,评论中建议的@Benjamin Lindley上述解决方案可能会与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);
}
}
并像下面的示例一样更改您的template print
:
template<typename Iterator>
void print(Iterator begin, Iterator end)
{
while (begin != end) {
detail::print_elem(cout, *begin) << endl;
++begin;
}
}