2008-12-03 11 views
18

Załóżmy, że istnieje funkcja szablonu w języku C++, która wykonuje użyteczne prace, ale także wysyła sekwencję wartości za pośrednictwem iteratora wyjścia. Przypuśćmy teraz, że ta sekwencja wartości jest czasami interesująca, ale w innych nie jest użyteczna. Czy istnieje klasa gotowa do użycia w klasie STL, która może być utworzona i przekazana do funkcji i zignorować wszelkie wartości, które funkcja próbuje przypisać do iteratora wyjściowego? Aby umieścić w inny sposób, wysłać wszystkie dane do/dev/null?Odrzucanie wyjścia funkcji wymagającej iteratora wyjścia

Odpowiedz

3

Czy masz dostępne wzmocnienie? Jeśli tak, możesz użyć funkcji function_output_iterator owijającej pustą funkcję.

To jednak nie jest idealne. Niezależnie od używanego iteratora nadal będzie konieczne utworzenie instancji value_type dla return in operator *, nawet jeśli następnie ją wyrzuci.

4

Nie jest trudno go napisać.

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; 
}; 

Nie przetestowałem tego i prawdopodobnie brakuje czegoś bardzo ważnego, ale myślę, że to jest idea.

+1

Pomysł jest dobry, ale nie sądzę, że potrzebujesz: T * operator ->() {return & m; } I powinieneś wyprowadzić ze stl :: output_iterator W tej implementacji kopia T jest wykonywana przy każdym przypisaniu poprzez iterator out. Czy mimo to można tego uniknąć? –

20

STL nie zapewnia takiej iteracji. Ale można zakodować to sam (przetestowane tego kodu):

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; } 
}; 

Nie potrzebuje żadnych danych używając siebie jako rezultat operator*. Wynik *it = x; nie jest używany w wyjściowych wymaganiach iteratora, więc możemy nadać mu typ zwrotu: void.


Edytuj: Przejdźmy do tego, jak działa ta operator*. Standard mówi w 24.1.2/1 temat wymagań iteratora wyjściowego, że w obu tych przypadkach:

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

że wynik tych wyrażeń nie jest używany. To, co czyni tę pracę:

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=`. 

Teraz nie musimy mieć żadnych danych, że wrócimy w operator*: Po prostu użyć samego iterator. Zwróć uwagę, że operator szablonowy = nie zastępuje wbudowanego operatora przypisania kopiowania. Jest nadal dostępny.

+0

Czy możesz lepiej wyjaśnić operator *? –

+0

Jest używany w połączeniu z szablonem operatora =. Tricky, użyłbym zagnieżdżonej klasy helper dev_null. Ponadto, pozwoliłbym operatorowi ++ (int) zwrócić * to natychmiast. Ta wersja jest nieskuteczna. – MSalters

+0

msalters, operacyjnym stanem semantyki zwracany jest nowy obiekt :) –

0

ja kopalnia na podstawie std::back_insert_iterator, ale bez pojemnika:

#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; } 
}; 

ta jest podobna do odpowiedzi Johannes, ale bez szablonu operator= że bierze cokolwiek. Lubię silne pisanie; Chcę, aby *it = wrong_type_thing był błędem kompilacji. Również to używa void dla różnych parametrów szablonu do std::iterator, takich jak wyjściowe iteratory w standardowej bibliotece.

Jest to podobne do rozwiązania Marka, ale (a) poprawnie dziedziczy po std::iterator i (b) nie ma niepotrzebnej zmiennej stanu wewnętrznego.