Ответ на @Rapptz является правильным, но для общего кода (то есть, когда не ясно априори ли идет речь о raw 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 = char, class traits = std::char_traits<charT>>
struct output_iterator_traits<std::ostream_iterator<T, charT, traits>>
:
std::iterator<std::output_iterator_tag, T>
{};
template <class charT, class traits = std::char_traits<charT>>
struct output_iterator_traits<std::ostreambuf_iterator<charT, traits>>
:
std::iterator<std::output_iterator_tag, charT>
{};
} // namespace xstd
неспециализированных версия просто наследует от std::iterator_traits<T>
, но для 6 выходных итераторов, определенных в заголовках <iterator>
и <memory>
, специализации наследуют от std::iterator<std::output_iterator_tag, V>
, где V
является типом появляться в качестве аргумента итератора operator=(const V&)
.
Для вставки итераторов, это соответствует typename Container::value_type
, для хранения сырых итераторов для T
, так и для ostream
и 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 */ };
}
}
будет работать прозрачно с обоих исходных указателей и выходных итераторов стандартной библиотеки.
Почему вы не используете вложенный тип, который происходит от итератора? [Живой пример] (http://coliru.stacked-crooked.com/a/3547c063ddfb1ddb) – dyp
@ dyp Я был глупым, 'back_insert_iterator' имеет вложенный typedef' container_type' даже – TemplateRex
См. Недавно добавленный живой пример. - ooooh, который является публичным участником. Я вижу – dyp