9 Ocak 2018 Salı

std::reference_wrapper

Giriş
Şu satırı dahil ederiz. Bu sınıf bir nesneyi veya bir metodu sarmalar.
#include <functional>
Default Constructor
Mevcut değil. Açıklaması şöyle
std::reference_wrapper is built as a wrapper to a reference, that's it. It must behave like a reference would, or else it wouldn't be a wrapper but something else. There are use-cases for it, which would possibly break if you allow a default value for it. If you need to have a null value, either use something else, like a pointer, or live with the limitations of references.
Copy Constructor
İmzası şöyle.
reference_wrapper(T& ref) noexcept : _ptr(std::addressof(ref)) {}
İmzası şöyle.
template <typename T>
reference_wrapper<T>::reference_wrapper(const reference_wrapper<T>&)
Bir reference_wrapper başka bir reference_wrapper nesnesine kopyalanabilir.
int v = 12;
std::reference_wrapper<int> x(v);
std::reference_wrapper<const int> y(x);  // (1) This works
Move Constructor
Mevcut değil. İmzası şöyle.
reference_wrapper(T&&) = delete;
get metodu
Şöyle yaparız. Sarmalanan nesneyi döner.
int i = 42;
std::list<std::reference_wrapper<int>> lst;

lst.push_back(i);           // we add a "reference" into the list
lst.front().get() = 10;     // we update the list
std::cout << i;             // the initial i was modified!
operator ()
İmzası şöyle. Sarmalanan metodu çağırır.
operator T& () const noexcept { return *_ptr; }
Açıklaması şöyle.
operator() returns std::result_of<T&(ArgTypes&&...), which is return value of the function stored and std::invoke call such function and forwards parameters to it.
Metodun içi şöyle.
template< class... ArgTypes >
typename std::result_of<T&(ArgTypes&&...)>::type
operator() ( ArgTypes&&... args ) const {
  return std::invoke(get(), std::forward<ArgTypes>(args)...);
}
Şöyle yaparız.
std::reference_wrapper<int(int)> ref = foo;
ref(5);

STL Map İçinde Kullanımı
Şöyle yaparız.
std::map<int, std::reference_wrapper<const int>> mb;
const int a = 5;
mb.emplace(0, std::cref(a));
STL Vector İçinde Kullanımı
1.Elimizde şöyle bir vector olsun.
std::vector<double> v(5, 10.3);
Başka bir veri yapısı içindeki elemana referans almak istersek şöyle yaparız. Böylece r vector'ü, v vector'ündeki elemanları değiştirir.
std::vector<std::reference_wrapper<double>> r(v.begin(),v.end());
2. Elimizde bir X içeren vector olsun ve bu vector'ü farklı alanlara göre sıralamak için şöyle yaparız.
std::vector<X> v; // elements of X in some order
std::vector<std::reference_wrapper<X const> > index1(v.begin(), v.end());
std::vector<std::reference_wrapper<X const> > index2(v.begin(), v.end());

// sort the indexes
std::sort(index1.begin(), index1.end(), by_property1);
std::sort(index2.begin(), index2.end(), by_property2);
Değişkenler İle Kullanımı
Şöyle yaparız.
#include <iostream>
#include <functional>  // for reference_wrapper
using namespace std;
int main()
{
    int x=5, y=7, z=8;
    reference_wrapper<int> arr[] {x,y,z};
    for (auto a:arr)
    cout<<a<<" ";
    return 0;
}
/* OUTPUT :-
5 7 8
*/
Metod İle Kullanımı
Şöyle yaparız.
int foo(int bar)
{
    return bar + 5;
}

int main()
{
    std::reference_wrapper<int(int)> ref = foo;
    ref(5);
}
Nesne İle Kullanımı
Object slicing'den kurtulup polymorphic davranış için kullanılabilir. Elimizde şöyle bir kod olsun
class base {
public:
  int id;

  virtual void f() const {
    cout << "base f()" << endl;
  }
};

class D1: public base {
public:
  void f() const {
    cout << "D1 f()" << endl;
  }
};

class D2: public base {
public:
  void f() const {
    cout << "D2 f()" << endl;
  }
};
Şöyle yaparız.
priority_queue<std::reference_wrapper<base>, deque<std::reference_wrapper<base>>,
  less<deque<std::reference_wrapper<base>>::value_type> > q;

D1 d1;
D2 d2;

q.push(d1);
q.push(d2);

const auto& b = q.top();
b.get().f();    // D1 f()

Hiç yorum yok:

Yorum Gönder