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
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.
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.
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.
Czy możesz lepiej wyjaśnić operator *? –
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
msalters, operacyjnym stanem semantyki zwracany jest nowy obiekt :) –
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.
- 1. Zrozumienie wyjścia z funkcji rekurencyjnej
- 2. Zamówienie wyjścia
- 3. Przekierowanie wyjścia funkcji do/dev/null
- 4. Pojedynczy krok do wyjścia z funkcji gdb
- 5. Formatowanie wyjścia konsoli C++
- 6. Przekierowywanie standardowego wyjścia c, a następnie resetowanie standardowego wyjścia
- 7. Gnu i formatowanie wyjścia
- 8. Ruby - każdy wyjścia offsetu
- 9. Perl - formatowanie wyjścia DateTime
- 10. Formatowanie wyjścia latex (to_latex)
- 11. Pomijanie wyjścia debugowania sbt
- 12. Objaśnienie wyjścia ldd
- 13. Status wyjścia polecenia ping
- 14. Stan tee i wyjścia
- 15. Interpretowanie wyjścia strace
- 16. Rurociągi dla wejścia/wyjścia
- 17. Wybór wyjścia audio JavaFX
- 18. Interpretowanie wyjścia StringToWordVector() - Weka
- 19. SQL Fiddle Błąd wyjścia
- 20. MVVM - Potwierdzenie wyjścia
- 21. R Błąd wyjścia Sweave
- 22. Strange Kod wyjścia
- 23. Wyjścia "+" i "-" polecenia Zadania
- 24. Obcięcie wyjścia w BASH
- 25. Opis wyjścia zespołu GHC
- 26. PHP - zagnieżdżone buforowanie wyjścia
- 27. Interpretacja wyjścia Intel_gpu_top
- 28. ograniczenia przekierowania wyjścia bash?
- 29. Przekierowanie wyjścia crona
- 30. Przekierowanie wyjścia Trace.axd
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ąć? –