@Rapptz 的答案是正确的,但对于通用代码(即,当不清楚先验是处理原始T*
的还是back_insert_iterator
标准库的其他输出迭代器之一时),需要一种更系统的方法。
为此,output_iterator_traits
在用户定义的类模板的定义下方namespace xstd
。
#include <iterator> // iterator, iterator_traits, input_iterator_tag, output_iterator_tag, random_access_iterator_tag
// back_insert_iterator, front_insert_iterator, insert_iterator, ostream_iterator, ostreambuf_iterator
#include <memory> // raw_storage_iterator
namespace xstd {
template<class T>
struct output_iterator_traits
:
std::iterator_traits<T>
{};
template< class OutputIt, class T>
struct output_iterator_traits<std::raw_storage_iterator<OutputIt, T>>
:
std::iterator<std::output_iterator_tag, T>
{};
template<class Container>
struct output_iterator_traits<std::back_insert_iterator<Container>>
:
std::iterator<std::output_iterator_tag, typename Container::value_type>
{};
template<class Container>
struct output_iterator_traits<std::front_insert_iterator<Container>>
:
std::iterator<std::output_iterator_tag, typename Container::value_type>
{};
template<class Container>
struct output_iterator_traits<std::insert_iterator<Container>>
:
std::iterator<std::output_iterator_tag, typename Container::value_type>
{};
template <class T, class charT, class traits>
struct output_iterator_traits<std::ostream_iterator<T, charT, traits>>
:
std::iterator<std::output_iterator_tag, T>
{};
template <class charT, class traits>
struct output_iterator_traits<std::ostreambuf_iterator<charT, traits>>
:
std::iterator<std::output_iterator_tag, charT>
{};
} // namespace xstd
非特化版本简单地继承自std::iterator_traits<T>
,但是对于定义在<iterator>
和<memory>
头文件中的 6 个输出迭代器,特化继承自std::iterator<std::output_iterator_tag, V>
whereV
是作为迭代器的参数出现的类型operator=(const V&)
。
对于插入迭代器,这对应于typename Container::value_type
, 对于原始存储迭代器到T
, 和 forostream
和ostreambuf
迭代器到T
和charT
, 分别。
形式的通用算法
template<class InputIt, class OutputIt>
auto my_fancy_algorithm(InputIt first, InputIt last, OutputIt dest)
{
using T = typename xstd::output_iterator_traits<OutputIt>::value_type;
for (; first != last; ++first) {
// ... construct arguments from *first
*dest++ = T{ /* arguments */ };
}
}
然后将透明地使用原始指针和标准库的输出迭代器。