7 Stimmen

Macht die perfekte Weiterleitung in C++0x reference_wrapper veraltet?

Wie immer gilt: Code zuerst:

#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 gibt es keine schöne Möglichkeit, Vorwärtsparameter durch Template-Funktionen zu perfektionieren. Deshalb haben die C++-Gurus ref und cref erfunden, um dieses Ziel zu erreichen.

Bedeutet das, dass ref, cref und Co. jetzt, da wir r-Wert-Referenz und perfekte Weiterleitung haben, veraltet sein sollten?

3voto

sellibitze Punkte 26706

Referenzumschläge sind immer noch nützlich. Dies ist der Fall, wenn es um das Speichern von Dingen geht. Mit Referenz-Wrappern können Sie zum Beispiel std::make_tuple und std::thread dazu bringen, Objekte zu erzeugen, die auf ein Argument verweisen, anstatt sie zu kopieren:

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

Bitte beachten Sie, dass

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

Zum Wohl! s

2voto

UncleBens Punkte 39755

Das setzt voraus reference_wrapper war dafür vorgesehen. Vielmehr scheint es vor allem darum zu gehen, die Übergabe von Funktionsobjekten per Referenz zu ermöglichen, wo sie normalerweise als Wert genommen werden würden. - Wenn Sie die Argumente als T&& Würde das nicht bedeuten, dass es nicht mehr möglich ist, die Dinge nach ihrem Wert zu beurteilen?

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X