2016-11-18 61 views
4

假設我有一些像這樣的代碼:我可以從基於範圍的元素中移動元素嗎?

std::vector<std::string> produce(const std::string& str){ 
    // create a vector based on input 
} 

void consume(const std::string& str){ 
    for (auto i:produce(str)) 
     // do some thing that use the str 
     // and I'd like to move it from the vector 
     some_process(str) // for example, move into this function 
} 

我想知道如果編譯器(I可以使用任一或VS2015 GCC 6)可以優化的元素移動到for循環。或者我應該怎麼做,因爲這個字符串可能會很長。

舊的開始結束循環還是協程幫助?

+0

@songyuanyao,這不就是將一個轉發引用綁定到迭代器的'operator *'返回的值嗎?並且由於迭代器將一個左值引用返回給'std :: string','std :: string &&&'將摺疊爲'std :: string&'。 [這是一個例子](http://coliru.stacked-crooked.com/a/14efce4c332a8b9f) – Alejandro

+0

@Alejandro我認爲你是對的。 – songyuanyao

回答

5

如果你想從載體some_function()移動元素只是做move明確:

void some_function(std::string str); 
void some_function(std::string &&str); // or explicitly 


for(auto &i:produce(str)) 
    some_function(std::move(i)); 

否則不明確通過移動元素融入for循環的意思。

1

只是auto&與明確的std::move就夠了。

不過是看中了現在

struct empty_t{}; 
template<class It,class B=empty_t>struct range_t:B{ 
    It b,e; 
    It begin()const{return b;} 
    It end()const{return e;} 
    range_t(It s,It f):b(std::move(s)),e(std::move(f)){} 
    // fancy 
    template<class S, class F> 
    range_t(B base, S s, F f):B(std::move(base)),b(s(*this)),e(f(*this)){} 
}; 
template<class It>range_t<It> range(It b, It e){return{std::move(b),std::move(e)};} 
template<class B, class S, class F> 
auto range(B base, S s, F f){ 
    auto It=std::result_of_t<s(base)>; 
    return range_t<It,B>{ 
    std::move(base),std::move(s),std::move(f) 
    }; 
} 
template<class R> 
auto move_from(R& r){ 
    using std::begin; using std::end; 
    return range(std::make_move_iterator(begin(r)), std::make_move_iterator(end(r))); 
} 
template<class R> 
auto move_from(R&& r){ 
    using std::begin; using std::end; 
    return range(
    std::move(r), 
    [](auto&r){return std::make_move_iterator(begin(r));}, 
    [](auto&r){return std::make_move_iterator(end(r));} 
); 
} 

,除非錯別字,

for(auto i:move_from(produce(str))) 
    some_function(std::move(i)); 

將有i是一個移動,從每個元素的副本。

但這是瘋了。

當您要迭代基於ranfe/container的代碼時,這種技術可能非常有用,該代碼可以與move-agnostic無關。現在

template<class R, class F> 
auto transform_to_vector(R&& r, F&& f){ 
    using std::begin; using std::end; 
    using rT=std::decay_t<std::result_of_t< f(*begin(std::forward<R>(r))) >>; 
    std::vector<rT> retval; 
    for(auto&& e:std::forward<R>(r)){ 
    retval.push_back(f(decltype(e)(e))); 
    } 
    return retval; 
} 

,調用上面move_from(x)爲你的「範圍」是不是與x稱這是不同的。你可以想象其他算法也是這樣寫的。

+0

_但這是瘋了 - 這次我必須同意:即使我喜歡它,對於OP也沒什麼意義。 :-) – skypjack