2008-12-03 4 views
18

Предположим, что в C++ есть функция шаблона, которая выполняет некоторую полезную работу, но также выводит последовательность значений через выходной итератор. Теперь предположим, что эта последовательность значений иногда интересна, но в других это не полезно. Есть ли готовый к использованию класс итератора в STL, который может быть создан и передан функции, и будет игнорировать любые значения, которые функция пытается назначить выходному итератору? Чтобы по-другому отправить все данные в/dev/null?Отказ от вывода функции, для которой нужен выходной итератор

ответ

3

У вас есть Boost? Если это так, вы можете использовать function_output_iterator, обертывая пустую функцию.

Это не идеальный вариант. Независимо от того, какой итератор вы используете, все равно нужно создать экземпляр value_type для возврата в operator *, даже если он затем отбросит его.

4

Нетрудно написать его.

template<typename T> 
class NullOutputIterator 
{ 
public: 
    NullOutputIterator() {} 
    NullOutputIterator& operator++() { return *this; } 
    NullOutputIterator& operator++(int) { return *this; } 
    T& operator*() { return m; } 
    T* operator->() { return &m; } 
private: 
    T m; 
}; 

Я не проверял это, и, вероятно, что-то важное отсутствует, но я думаю, что это идея.

+1

Идея хорошая, но я не думаю, что вам нужно: T * operator ->() {return & m; } И вы должны получить из stl :: output_iterator С этой реализацией копия T выполняется при каждом присваивании через итератор. Есть ли вообще избежать этого? – 2008-12-03 01:15:36

20

STL не предоставляет такой итератор. Но вы могли бы кодировать его самостоятельно (проверено, что код):

struct null_output_iterator : 
    std::iterator< std::output_iterator_tag, 
        null_output_iterator > { 
    /* no-op assignment */ 
    template<typename T> 
    void operator=(T const&) { } 

    null_output_iterator & operator++() { 
     return *this; 
    } 

    null_output_iterator operator++(int) { 
     return *this; 
    } 

    null_output_iterator & operator*() { return *this; } 
}; 

Он не нуждается в каких-либо данных, используя себя в качестве результата operator*. Результат *it = x; не используется в требованиях выходного итератора, поэтому мы можем присвоить ему тип возврата void.


Редактировать: Давайте рассмотрим, как это работает operator*. Стандарт говорит, что в 24.1.2/1 о требованиях итератора вывода, что в обоих этих случаях:

*it = t; 
*it++ = t; 

Это результат этих выражений не используется. Вот что делает эту работу:

null_output_iterator it; 
*it; // returns a null_output_iterator& per definition of the `operator*`. 
*it = some_value; // returns void per definition of the templated `operator=`. 

Теперь нам не нужно иметь каких-либо данных, которые мы возвращаем в operator*: Мы просто использовать сам итератор. Обратите внимание, что шаблонный оператор = не перезаписывает оператор присваивания встроенной копии. Он по-прежнему предоставляется.

+0

Не могли бы вы лучше объяснить оператора *? – 2008-12-03 01:21:01

0

Я основан на шахте std::back_insert_iterator, но без контейнера:

#include <iterator> 

template<typename T> 
class NullOutputIter 
    : public std::iterator<std::output_iterator_tag,void,void,void,void> 
{ 
public: 
    NullOutputIter &operator=(const T &) { return *this; } 
    NullOutputIter &operator*() { return *this; } 
    NullOutputIter &operator++() { return *this; } 
    NullOutputIter operator++(int) { return *this; } 
}; 

Это похоже на ответ Johannes, но без шаблона operator=, который принимает любые. Мне нравится сильная печать; Я хочу, чтобы *it = wrong_type_thing была ошибкой времени компиляции. Также это использует void для различных параметров шаблона до std::iterator, как итераторы вывода в стандартной библиотеке.

Это также похоже на решение Марка, но (а) оно правильно наследует от std::iterator и (b) оно не имеет ненулевой переменной внутреннего состояния.

 Смежные вопросы

  • Нет связанных вопросов^_^