2010-12-01 7 views
7

Wie üblich Code zuerst:Ist die perfekte Weiterleitung in C++ 0x reference_wrapper veraltet?

#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 
} 

In C++ 98, haben wir nicht eine schöne Art und Weise Parameter durch Template-Funktionen perfekt vereint vorwärts. Also erfanden die C++ - Gurus Ref und Cref, um dieses Ziel zu erreichen.

Nun, da wir r-Wert Referenz und perfekte Weiterleitung hatten, bedeutet das, dass ref und cref und dergleichen veraltet sein sollten?

Antwort

3

Referenzwrapper sind immer noch nützlich. Dies ist der Fall, wenn es darum geht, Dinge zu speichern. Zum Beispiel mit Bezug Wrapper können Sie std :: machen make_tuple und std :: Thread-Objekte, die zu einem gewissen Argumente statt zu kopieren verweisen erstellen:

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(); 
} 

Beachten Sie, dass

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

Prost! s

2

Das ist unter der Annahme reference_wrapper war dafür vorgesehen. Vielmehr scheint es vor allem darum zu gehen, Funktionsobjekte durch Referenz zu übergeben, wo sie normalerweise werthaltig wären. - Wenn Sie stattdessen Argumente wie T&& nehmen würden, würde das nicht bedeuten, dass das Überschreiten von Dingen unmöglich wird?

#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 
}