Moving in range-based loop in generic C++ code? -


imagine have generic pseudo-code:

template<typename iterable> void f(iterable&& iterable) {    ... } 

we want handle rvalue , lvalue references iterable objects1, , idea function handles container performing operations element element.

it plausible want forward reference specification of container elements. in other words, if iterable rvalue reference, function have move elements container.

using c++17, do

auto [begin, end] = [&] {     if constexpr(std::is_lvalue_reference_v<iterable>)         return std::array{std::begin(iterable),                           std::end(iterable)};     else         return std::array{             std::make_move_iterator(std::begin(iterable)),             std::make_move_iterator(std::end(iterable))}; }(); std::for_each(begin, end, [&](auto&& element) {     ... }); 

obviously, not best code maintain2, error prone , not easy optimize compiler.

my question is: possible, future c++ standards, introduce concept of forwarding range-based loops? nice if this

for(auto&& el : std::move(iterable)) {     ... } 

could handle el rvalue reference. in way, possible:

template<typename iterable> void f(iterable&& iterable) {     for(auto&& el : std::forward<iterable>(iterable))     {         /*          *  el forwarded lvalue reference if iterable lvalue reference,          *  rvalue reference if iterable rvalue reference          */         external_fun(std::forward<decltype(el)>(el));     } } 

i concerned code-breaking changes, @ same time not able think situations in passing rvalue reference argument of range based loop expected work without moving objects.

as suggested, tried write down how change 6.5.4 section of standard. draft can read at address.

do think possible introduce feature without introducing serious issues?

1checked c++20 concepts or static_asserts
2and it's quite worse without c++17

this won't work. fundamentally there 2 kinds of things can iterate over: own elements, , don't. non-owning ranges, value category of range immaterial. don't own elements , can't safely move them. range-based for loop must work both kind of ranges.

there corner cases consider (e.g., proxy iterators). range-based for loop syntax sugar imposes minimal set of requirements on thing being iterated over. benefit can iterate on lots of things. cost doesn't have room clever.


if know iterable in fact owns elements (so moving safe), need function forwards according value category of other thing:

namespace detail {     template<class t, class u>     using forwarded_type = std::conditional_t<std::is_lvalue_reference<t>::value,                                               std::remove_reference_t<u>&,                                                std::remove_reference_t<u>&&>; } template<class t, class u> detail::forwarded_type<t,u> forward_like(u&& u) {     return std::forward<detail::forwarded_type<t,u>>(std::forward<u>(u)); } 

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -