Giriş
Şu satırı dahil ederiz. Bu sınıf bir nesneyi veya bir metodu sarmalar.
Bu sınıf bizi dangling reference probleminden kurtarır. Çünkü rvalue değerlerle çalışmaz.
Örnek
Elimizde şöyle bir kod olsun. Bu kod dangling reference yüzünden hatalıdır.
İmzası şöyle.
Mevcut değil. İmzası şöyle.
Şöyle yaparız. Sarmalanan nesneyi döner.
İmzası şöyle. Sarmalanan metodu çağırır.
STL Map İçinde Kullanımı
Şöyle yaparız. lvalue değere reference elde ederiz.
1.Elimizde şöyle bir vector olsun.
Değişkenler İle Kullanımı
Örnek
Şöyle yaparız. Değişkenin adresini elde ederiz.
Şöyle yaparız. Pointer'ın adresini elde ederiz.
Metod İle Kullanımı
Object slicing'den kurtulup polymorphic davranış için kullanılabilir. Elimizde şöyle bir kod olsun
Şu satırı dahil ederiz. Bu sınıf bir nesneyi veya bir metodu sarmalar.
#include <functional>
Dangling Reference ProblemiBu sınıf bizi dangling reference probleminden kurtarır. Çünkü rvalue değerlerle çalışmaz.
Örnek
Elimizde şöyle bir kod olsun. Bu kod dangling reference yüzünden hatalıdır.
#include <vector>
#include <iostream>
std::vector<int> someNums()
{
return {3, 5, 7, 11};
}
class Woop
{
public:
Woop(const std::vector<int>& nums) : numbers(nums) {}
void report()
{
for (int i : numbers)
std::cout << i << ' ';
std::cout << '\n';
}
private:
const std::vector<int>& numbers;
};
int main()
{
Woop woop(someNums());
woop.report();
}
Düzeltmek için şöyle yaparız#include <functional>
class Woop
{
public:
using NumsRef = ::std::reference_wrapper<const std::vector<int>>;
Woop(NumsRef nums) : numbers_ref{nums} {}
void report()
{
for (int i : numbers_ref.get())
std::cout << i << ' ';
std::cout << '\n';
}
private:
NumsRef numbers_ref;
};
Böylece şu kod derlenmezWoop woop{someNums()}; // error
woop.report();
Şöyle yaparız.auto nums{someNums()};
Woop woop{nums}; // ok
woop.report();
veya şöyle yaparız.auto nums{someNums()};
Woop woop{::std::ref(nums)}; // even better because explicit
woop.report();
Default Constructor
Mevcut değil. Açıklaması şöylestd::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 ConstructorMevcut 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.Metodun içi şö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.
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. lvalue değere reference elde ederiz.
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);
STL Array İçinde Kullanımı
Şöyle yaparız
int a = 10;
int b = 20;
int c = 20;
using rint = std::reference_wrapper<int>;
std::array<rint,3> x = {a,b,c};
std::cout << "a " << a << std::endl;
x[0].get()=11;
std::cout << "a " << a << std::endl;
Örnek
Şöyle yaparız. Değişkenin adresini elde ederiz.
#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
*/
ÖrnekŞöyle yaparız. Pointer'ın adresini elde ederiz.
#include <functional>
template <typename T>
struct Foo
{
Foo(T arg) : ptr(arg)
{
}
T ptr;
};
int main()
{
int* a = new int(6);
Foo<std::reference_wrapper<int*>> foo1(std::ref(a));
foo1.ptr[0] = 1; // ok
// This also works
int* b = new int(6);
Foo<std::reference_wrapper<decltype(b)>> foo2(std::ref(b));
// and this too
foo1 = foo2;
// Or, if you use c++17, even this
Foo foo3(std::ref(b));
}
Metod İle Kullanımı
Örnek
Şöyle yaparız. Metodun adresini elde ederiz.
Nesne İle KullanımıŞöyle yaparız. Metodun adresini elde ederiz.
int foo(int bar)
{
return bar + 5;
}
int main()
{
std::reference_wrapper<int(int)> ref = foo;
ref(5);
}
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. Böylece priority_queue veri yapısı base& şeklinde çalışır.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