[signals] What's special about iterators passed to combiners?

A reader of my book noticed that the sample program at http://en.highscore.de/cpp/boost/src/4.2.8/main.cpp which uses a combiner to return the smallest value of all slot values is buggy. The combiner's implementation is rather simple as iterators are simply forwarded to std::min_element(): template <typename T> struct min_element { typedef T result_type; template <typename InputIterator> T operator()(InputIterator first, InputIterator last) const { return *std::min_element(first, last); } }; As simple as the implementation is: This combiner does not return the smallest value but always the value the first iterator refers to (at least with VC++ 2008 and g++ 4.2.1). This can be easily tested by swapping the return values of the two functions func1() and func2() in the sample program. First I was trying to find a fix - temporarily copying the values to a container is all what is needed: T operator()(InputIterator first, InputIterator last) const { std::vector<T> v(first, last); return *std::min_element(v.begin(), v.end()); } Then I was trying to understand what's special about the iterators. Please look at the following code and guess whether the values printed will be different or not: T operator()(InputIterator first, InputIterator last) const { InputIterator temp = first; ++first; std::cout << *first << std::endl; std::cout << *temp << std::endl; } If you think you get two different values then you'll be as surprised as I am: Both iterators temp and first return the second value in the range [first, last). I can't find any explanation in the Boost.Signals documentation. I wouldn't be surprised though if this is a known issue because there is a sample combiner called maximum used (see http://www.boost.org/doc/libs/1_43_0/doc/html/signals/tutorial.html#id173040...) which doesn't use an algorithm from the C++ standard (I guess intentionally?). Anyway: Is this a bug? If it isn't is there a recommended work-around (apart from temporarily copying values to a container)? Then it's probably not safe to use any C++ standard algorithm in combiners? Could this be added to the FAQ or anywhere else in the Boost.Signals documentation? Boris

On 14 May 2010 15:13, Boris Schaeling
A reader of my book noticed that the sample program at http://en.highscore.de/cpp/boost/src/4.2.8/main.cpp which uses a combiner to return the smallest value of all slot values is buggy. The combiner's implementation is rather simple as iterators are simply forwarded to std::min_element():
template <typename T> struct min_element { typedef T result_type;
template <typename InputIterator> T operator()(InputIterator first, InputIterator last) const { return *std::min_element(first, last); } };
Your choice of typename here has me worried, since std::min_element requires ForwardIterators, not InputIterators. That's also the explanation for your last code example; it uses the iterators in a way not allowed for input iterators.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Friday 14 May 2010, Boris Schaeling wrote:
A reader of my book noticed that the sample program at http://en.highscore.de/cpp/boost/src/4.2.8/main.cpp which uses a combiner to return the smallest value of all slot values is buggy. The combiner's implementation is rather simple as iterators are simply forwarded to std::min_element():
min_element requires a forward iterator. The slot iterators are only input iterators.
Then I was trying to understand what's special about the iterators. Please look at the following code and guess whether the values printed will be different or not:
T operator()(InputIterator first, InputIterator last) const { InputIterator temp = first; ++first; std::cout << *first << std::endl; std::cout << *temp << std::endl; }
If you think you get two different values then you'll be as surprised as I am: Both iterators temp and first return the second value in the range [first, last).
temp no longer has to be valid after first is incremented (see definition of input iterator). -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkvtUZcACgkQ5vihyNWuA4VAlgCeI5+8kRxe0YOj0m9Pu1tBMgBJ BvgAnApE7eG+SDyD0mZ9Ucca6oIvU9Zg =0lZi -----END PGP SIGNATURE-----

On Fri, 14 May 2010 15:35:19 +0200, Frank Mori Hess
[...]min_element requires a forward iterator. The slot iterators are only input iterators.
Thanks for both of your answers! The more confusing the problem the shorter and simpler the explanation. :) Boris
[...]
participants (3)
-
Boris Schaeling
-
Frank Mori Hess
-
Scott McMurray