将模板函数传递给std::for_each
passing template function to std::for_each
我想写一个简单的模板函数,打印一些容器的每个元素,而不使用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
有明显的原因,但随后的代码不编译。我该怎么做呢?
您可以使用:
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);
});
另一个选项:
template <typename T> void print_all(T beg, T end) {
std::for_each(beg, end, print_with_space<decltype(*beg)>);
std::cout << 'n';
}
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';
}
最灵活的解决方案是使print_with_space
成为函数对象,这将适用于所有版本的c++。
这提供了许多优点:
- 无需在调用现场指定模板类型。
- 无需手动类型扣除。
- 部分专门化可以通过让函子服从于模板化的自由函数来实现。
:
#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;
}
相关文章:
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- std::memory_order for std::atomic:<T>:wait
- 在基于范围的 for 循环期间插入 std::list 的后面
- 为什么当我为 for(auto& it : myUnorderedMap) {... = std::move(it.second)} 时,我会得到一个 const 引用?
- 运算符 << 操作加载的 API for std::endl?
- google test PrintTo for std::set<std::string>
- std::memcpy vs std::copy_n for legacy c structs
- C++11 基于范围的 for 循环,用于 std::list
- For-loop或std::any_of,我应该使用哪一个?
- 从 std::ostream 重载 << 运算符时,为什么编译器会给出"too many parameters for this operator function"错误?
- std::hash for std::chrono::duration
- 如何修复以下错误"no match for call to '(std::tr1::shared_ptr<_iobuf*>) (FILE*&)'"
- 访问类的 std::vector 与 for 循环中的 custum 类对象
- Hash for a std::pair, for use in an unordered_map
- 计算使用 C++ std 函数而不是 for 循环的大 O
- 使用 OpenMP 在并行 for 循环中使用 std::cout
- 使用 std::vector<Particle> 粒子;函数 .at() 不能与迭代器一起使用,它作为 for 循环中的参数
- C++ SFINAE : is_constructible for const char[] vs std::strin
- 使用 std::min "no matching function for call to ‘min(<brace-enclosed initializer list>)’"时出错
- 类型安全 - all_of/ any_of/ none_of for std::tuple