
On Sun, Jun 17, 2012 at 5:33 AM, Michel Morin <mimomorin@gmail.com> wrote:
Michel Morin wrote:
I implemented this approach as a range adaptor (with the aid of rvalue references and decltype C++11 features):
for (auto x : std::string("Hello world!") | moved | reversed) { /*...*/ }
When an rvalue range is piped to `moved` adaptor, it returns `moved_range`.
Side note:
[...]
* When the input is an **lvalue** range, `moved` adaptor does nothing (it just returns the reference) in the current implementation:
template <typename Range> inline Range& operator|(Range& rng, move_forwarder) { return rng; }
So `forwarded` might be better naming. (I also found that Range Library Proposal (N1871) includes `moved` adaptor for different purpose; `moved` adaptor in N1781 wraps iterators into `move_iterator`.)
I think moved and move_forwarder are confusing names as I would think they would take a meaning similar to that in N1871/N1781/whatever (i.e., wrapping the adapted range's iterators in move_iterators). Forwarded is better, but my suggestion is something along the lines of "by_value" and "by_value_if_rv": for(auto x : std::string("Hello World!") | by_value_if_rv | reversed) // or, in this case, using simply "by_value" would be equivalent ...although it doesn't have the right grammatical tense :( But I think the important semantic property about this wrapper is that it effectively signals the "range adaptor operator|" to adapt *by value*, and the fact that we move to achieve this is just consequence (i.e., most of the time, we could copy, it would just be less efficient). Question: Why have the operator| on the moved_range return another moved_range, accumulating the adaptors explicitly in a Fusion sequence? Couldn't we just return the usual range adaptor types, with special metafunction logic to switch to by-value storage (rather than the default reference storage) of the adapted range when its a moved_range or an adaptation of a moved_range? - Jeff