2010-12-01 14 views
7

Como de costumbre, el código primero:¿El reenvío perfecto en C++ 0x hace que reference_wrapper esté en desuso?

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

En C++ 98, que no tienen una buena manera de PEFECT hacia adelante a través de los parámetros de las funciones de plantilla. Entonces los gurús de C++ inventaron ref y cref para lograr ese objetivo.

Ahora que hemos tenido una referencia de valor r y un reenvío perfecto, ¿significa que deben rechazarse ref y cref y similares?

Respuesta

3

Los envoltorios de referencia siguen siendo útiles. Este es el caso cuando se trata de almacenar cosas. Por ejemplo, con envolturas de referencia se puede hacer std :: make_tuple y std :: hilo de crear objetos que hacen referencia a un argumento en lugar de copiarlos:

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

Tenga en cuenta que

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

Salud! s

2

Suponiendo que reference_wrapper fue diseñado para eso. Más bien, parece ser principalmente sobre permitir el paso de objetos de función por referencia donde normalmente se tomarían por valor. - Si tomas argumentos como T&&, ¿no significaría eso que pasar cosas por valor se hace imposible?

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