/******************************************************************************/ /* */ /* FILE: december.cpp */ /* */ /* Slowly, I begin to appreciate the STL */ /* ===================================== */ /* */ /* Compiled and tested with Visual C++ V6.0 */ /* */ /* V1.00 19-DEC-2000 P. Tellenbach http://www.heimetli.ch/ */ /* */ /******************************************************************************/ #include <iostream> #include <algorithm> class Process { public: operator()( char ch ) { std::cout.put( ch ) ; } operator int() { return 0 ; } } ; int main() { char *ps = "Hello world !\n" ; return std::for_each( ps, std::find(ps,(char *)0,'\0'), Process() ) ; }
Update 19. December 2020
The compiler complained about operator() without a return type. Declaring the method as void corrected the problem.
The warnings about const and non-const were also easy to fix.
But then the program printed a lot of nonsense and crashed!
This turned out to be a consequence of an optimization in the implementation of the find-algorithm in the library. The function checks the iterator-type and calls a different version for random access iterators. This version determines the distance between the iterators and tries to partially unroll the loop. The nullptr passed as end of the sequence produces a negative number and that produces an incorrect result.
This could be solved by adding a large number to the pointer, but I decided to use a custom iterator which identifies itself as an input-iterator.
/******************************************************************************/ /* */ /* FILE: december.cpp */ /* */ /* Slowly, I begin to appreciate the STL */ /* ===================================== */ /* */ /* Compiled and tested with Visual C++ V6.0 */ /* */ /* V1.00 19-DEC-2000 P. Tellenbach http://www.heimetli.ch/ */ /* */ /* Compiled and tested with g++ V8.3.0 */ /* */ /* V2.00 19-DEC-2020 P. Tellenbach https://www.heimetli.ch/ */ /* */ /******************************************************************************/ #include <iostream> #include <algorithm> #include <iterator> class CharIterator : public std::iterator<std::input_iterator_tag, char> { const char* ptr; public: CharIterator( const char* p ) : ptr( p ) { } CharIterator( const CharIterator &it ) : ptr( it.ptr ) { } CharIterator& operator++() { ++ptr ; return *this ; } CharIterator operator++(int) { CharIterator tmp(*this) ; operator++() ; return tmp; } bool operator==(const CharIterator& rhs) const { return ptr == rhs.ptr ; } bool operator!=(const CharIterator& rhs) const { return ptr != rhs.ptr ; } const char& operator*() { return *ptr ; } }; class Process { public: void operator()( char ch ) { std::cout.put( ch ) ; } operator int() { return 0 ; } } ; int main() { const char *ps = "Hello world !\n" ; return std::for_each( CharIterator(ps), std::find(CharIterator(ps),CharIterator(nullptr),'\0'), Process() ) ; }