Означает ли идеальная пересылка в C ++ 0x устаревание reference_wrapper? - PullRequest
7 голосов
/ 01 декабря 2010

Как обычно, сначала код:

#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 у нас нет хорошего способа отточить параметры вперед с помощью функций шаблона.Таким образом, гуру C ++ изобрели ref и cref для достижения этой цели.

Теперь, когда у нас есть ссылка на r-значение и идеальная переадресация, означает ли это, что ref и cref и тому подобное следует исключить?

Ответы [ 2 ]

3 голосов
/ 04 декабря 2010

Справочные обертки по-прежнему полезны. Это тот случай, когда речь идет о хранении вещей. Например, с помощью упаковщиков ссылок вы можете сделать так, чтобы std :: make_tuple и std :: thread создавали объекты, которые ссылаются на некоторый аргумент, а не копируют их:

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 голосов
/ 02 декабря 2010

Это предполагает, что 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...