我正在尝试编写一个简单的模板函数,它可以打印某个容器的每个元素,而不使用for循环。到目前为止,我有
#include <iostream>
#include <vector>
#include <algorithm>
template <typename T> void print_with_space(T x){
std::cout << x << ' ';
}
template <typename T> void print_all(T beg, T end){
std::for_each(beg, end, print_with_space<int>);
std::cout << '\n';
}
int main(){
int a[] = {1, 2, 3};
std::vector<int> v(a, a+3);
print_all(v.begin(), v.end());
return 0;
}
代码编译并运行,但仅仅是因为我将print_with_space<int>
放在print_all
的实现中。我想明显有print_with_space
,但是代码不能编译。我该怎么做?
答案 0 :(得分:5)
您可以使用:
std::for_each(beg, end, [](const typename T::value_type& value) {
print_with_space(value);
});
T
的类型为std::vector<>::iterator
,为RandomAccessIterator
。每个RandomAcessIterator
都有一个基础类型,由value_type
公开。
因此,如果您通过std::vector<int>::iterator
,则std::vector<int>::iterator::value_type
将是int
。
现在您已拥有该类型,您可以创建一个lambda,它将在每次迭代时执行。
在C ++ 14中,你甚至可以这样做:
//'auto' automatically deduces the type for you
std::for_each(beg, end, [](const auto& value) {
print_with_space(value);
});
答案 1 :(得分:1)
C ++ 03的替代方案:
#include <iterator>
template <typename T> void print_all(T beg, T end)
{
typedef typename std::iterator_traits<T>::value_type val_t;
std::for_each(beg, end, print_with_space<val_t>);
std::cout << '\n';
}
答案 2 :(得分:1)
另一种选择:
template <typename T> void print_all(T beg, T end) {
std::for_each(beg, end, print_with_space<decltype(*beg)>);
std::cout << '\n';
}
答案 3 :(得分:1)
最灵活的解决方案,适用于所有版本的c ++,是使print_with_space
成为一个函数对象。
这带来了许多好处:
如:
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
// basic implementation
template<class T> void impl_print_with_space(const T& x)
{
std::cout << x << ' ';
}
// what about special handling for strings?
template<class C, class Ch, class Alloc>
void impl_print_with_space(const std::basic_string<C, Ch, Alloc>& x)
{
std::cout << std::quoted(x) << ' ';
}
// functor
struct print_with_space
{
template<class T> void operator()(const T& x) const
{
impl_print_with_space(x);
}
};
template <typename Iter> void print_all(Iter beg, Iter end)
{
std::for_each(beg, end, print_with_space());
std::cout << '\n';
}
int main(){
int a[] = {1, 2, 3};
std::vector<int> v(a, a+3);
print_all(v.begin(), v.end());
auto b = std::vector<std::string> { "hello", "world" };
print_all(b.begin(), b.end());
return 0;
}