
Doug Gregor <dgregor@cs.indiana.edu> writes:
... [snipped]
Unfortunately, some of them are pretty important. For instance, if one tried to have a result_type that is an iterator, copying a slot_call_iterator that has not been dereferenced could result in undefined behavior, because the iterator would have been default-constructed and therefore singular. That doesn't make the optimization invalid, of course, but it does limit where we can apply the optimization.
This is just a thought, but I believe this could be fixed by defining the caching object so that it only copies the cached value if the cache is valid.
We could do it at compile time using some combination of type traits, probably. Unfortunately, those that come to mind--is_default_constructible and is_assignable--don't give us all the information we need, because iterators will return "true" for both but will have the wrong behavior. We would need to introduce a new trait for this.
Actually, there is one other corner case that's really ugly. The combiner could theoretically do something like this:
template<typename InputIterator> result_type operator()(InputIterator first, InputIterator last) { while (first != last) { InputIterator annoying = first; *first; if (*annoying) /* ... */ } }
I *think* that's valid code according to the Input Iterator requirements (but not 100% sure!), and without the pointer "*annoying" would call the slot again...
Oh, I know a solution now... we stick an "optional<R> slot_result" into the signal's operator() and keep a pointer to that variable in the slot_call_iterator. The optional<R> has nearly the same effect as the cache interface you mentioned, but it doesn't require default-constructibility; storing a pointer to it ensures that slot_iterator copies are fast and that all slot_iterators see the updates (for those truly pathological combiners).
Doesn't the optional<R> value have to be allocated on the heap when a slot_call_iterator is created, and doesn't it have to be a shared_ptr so that the copy semantics will be correct? I ask because I'm trying to avoid any heap allocation, which I think of as slow. Robert