2010-12-01 84 views
7

像往常一樣,代碼首先:在C++ 0x中完美轉發是否使reference_wrapper不被使用?

#include <functional> 

using namespace std; 
using namespace std::tr1; 

void f(int& r) { r++; } 

template<class F, class P> void g1(F f, P t) { f(t); } 
template<class F, class P> void g2(F f, P&& t) { f(forward<P>(t)); } 

int main() 
{ 
    int i = 0; 

    g1(f, ref(i)); // old way, ugly way 
    g2(f, i); // new way, elegant way 
} 

在C++ 98中,我們沒有一個很好的辦法pefect向前模板函數的參數。所以C++大師們發明了ref和cref來實現這個目標。

現在我們已經有了r值引用和完美的轉發,這是否意味着ref和cref之類的應該被棄用?

回答

3

參考包裝仍然有用。這是關於存儲事物的情況。例如,參照包裝可以使的std :: make_tuple和std ::線程創建這是指一些說法,而不是將它們複製的對象:

class abstract_job 
{ 
public: 
    virtual ~abstract_job() {} 
    virtual void run() = 0; 
}; 

class thread 
{ 
public: 
    template<class Fun, class... Args> 
    thread(Fun&& f, Args&&... args) 
    { 
     typedef typename decay<Fun>::type fun_type; 
     typedef decltype(make_tuple(forward<Args>(args)...)) tuple_type; 
     unique_ptr<abstract_job> ptr (new my_job<fun_type,tuple_type>(
      forward<Fun>(fun), 
      make_tuple(forward<Args>(args)...) 
     )); 
     // somehow pass pointer 'ptr' to the new thread 
     // which is supposed to invoke ptr->run(); 
    } 
    ... 
}; 

... 

void foo(const int&); 

int main() 
{ 
    thread t (foo, 42); // 42 is copied and foo is invoked 
    t.join()   // with a reference to this copy 
    int i = 23; 
    thread z (foo, std::cref(i)); // foo will get a reference to i 
    z.join(); 
} 

記住,

make_tuple(std::ref(i)) // yields a tuple<int&> 
make_tuple(  i) // yields a tuple<int> 

乾杯! s

2

這就是假設reference_wrapper是爲此而設計的。相反,它似乎主要是允許通過引用傳遞函數對象,而這些函數對象通常是通過值來獲取的。 - 如果你想以T&&來代替,那麼這是否意味着按價值傳遞事物變得不可能?

#include <iostream> 
#include <functional> 
#include <algorithm> 

class X: public std::unary_function<int, void> 
{ 
    int n; 
public: 
    X(): n(0) {} 
    void operator()(int m) {n += m;} 
    int get_n() const { return n; } 
}; 

template <class Iter, class Fun> 
void for_each(Iter from, Iter to, Fun&& fun) 
{ 
    for (; from != to; ++from) 
     fun(*from); 
} 

int main() 
{ 
    int a[] = {1, 2, 3}; 
    X x1; 
    ::for_each(a, a + 3, x1); 
    std::cout << x1.get_n() << '\n'; //6 

    X x2; 
    std::for_each(a, a + 3, x2); 
    std::cout << x2.get_n() << '\n'; //0 

    X x3; 
    std::for_each(a, a + 3, std::ref(x3)); 
    std::cout << x3.get_n() << '\n'; //6 
}