2016-11-18 1 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 
} 

コンパイラが(私はVS2015またはGCC 6のいずれかを使用してもよい)forループに要素を移動させるように最適化することができれば私はだろう。または、文字列がかなり長くなる可能性があるので、私はそれを動かすために何をするべきですか?

古いものはループやコルーチンのヘルプのために終了しますか?あなたはsome_function()にそのベクトルの要素を移動したい場合は

+0

@songyuanyao、それはイテレータの 'operator *'によって返された値に転送参照をバインドしませんか?そしてイテレータは左辺参照を 'std :: string'に返しますので、' std :: string&&& 'は' std :: string& 'に崩壊します。 [ここに例があります](http://coliru.stacked-crooked.com/a/14efce4c332a8b9f) – Alejandro

+0

@Alejandro私はあなたが正しいと思います。 – songyuanyao

答えて

5

だけで明示的に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が移動-からされている各要素のコピーがあります。

しかし、それは非常識です。

この手法は、移動不能にしたいラウンド/コンテナベースのコードを繰り返しているときに便利です。

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

関連する問題