12 Kasım 2018 Pazartesi

Perfect Forwarding Nedir

Giriş
perfect forwarding ve forwarding reference iç içe kavramlar. Metodun parametresinin T&& şeklinde tanımlanması demek.

Örnek
Şöyle yaparız.
template <typename... Args>
void foo(Args&&... args) { ... }
Örnek
Şöyle yaparız.
template <typename T>  
void f(T && t);
Bu metod içindeki "T && t" parametresi normalde r-value reference olarak adlandırılır. Ancak T template parametresi ile birlikte kullanılınca ismi forwarding reference olur. Açıklaması şöyle
forwarding reference is an rvalue reference to a cv-unqualified template parameter. If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.
forwarding reference ismi standarda geç girdi. Girmeden önce Scott Meyers "Universal Reference" ismini kullanıyordu.

Normalde sınıfımıza hem lvalue hem de rvalue atamak istersek normalde iki tane setter yazmamız gerekir.
void SetBar(const bar &src) { m_barInstance = src; }
void SetBar(bar &&src) { m_barInstance = std::move(src); }
Perfect forwarding ile tek bir template metod kullanarak her iki setter'ı da gerçekleştirebiliyoruz.
class foo
{
  public:
    template <typename T>
    void SetBar(T&& otherBarInstance) {
      m_barInstance = std::forward<T>(otherBarInstance); 
    }

  private:
      bar m_barInstance;  
};
Böylece metodumuzu her şekilde çağırabiliyoruz.
Bar b{};
my_foo.SetBar(b);           //copy
my_foo.SetBar(std::move(b)) //move
my_foo.SetBar(Bar{});       //move
perfect forwarding nedir ve lambda
Normal metodlarda T tipi bellidir. Şöyle yapabiliriz.
template <class T> void f(T&& x) {myfunction(std::forward<T>(x));}
lambda ile auto kullanılıyorsa T tipi belli değildir. Şöyle yapamayız
auto f = [](auto&& x){myfunction(std::forward</*?*/>(x));}
Onun yerine şöyle yaparız.
auto f = [](auto&& x){myfunction(std::forward<decltype(x)>(x));}
veya daha kısaca şöyle yaparız.
auto f = [](auto&& x){myfunction(decltype(x)(x));}

Hiç yorum yok:

Yorum Gönder