Hej
Próbuje zrozumieć jak działa perfect forwarding. W sensie na jakim etapie i z jakimi kosztami może się to wiązać i coś mi umyka. Dla takiego programu testowego :
#include <iostream>
#include <utility>
using namespace std;
struct NoMoveHardToCopy
{
NoMoveHardToCopy(int iArg)
: sec(iArg) {
cout << "c\n";
}
NoMoveHardToCopy(const NoMoveHardToCopy& aOther)
: sec(aOther.sec) {
cout << "cc\n";
}
NoMoveHardToCopy& operator=(const NoMoveHardToCopy& aOther) {
sec = aOther.sec;
cout << "co\n";
return *this;
}
NoMoveHardToCopy(NoMoveHardToCopy&& ) = delete;
NoMoveHardToCopy& operator=(NoMoveHardToCopy&& ) = delete;
int sec;
};
struct S
{
S(int arg) : sec(arg) {}
int sec;
};
int pf()
{
return 0;
}
#if 1 // version with forward and rvalues
template <typename T, typename... Args>
int pf(T&& tObj, Args&&... args)
{
std::cout << "Iteration " << tObj.sec << " ";
return tObj.sec + pf(forward<Args>(args)...);
}
#else // no forward
template <typename T, typename... Args>
int pf(T&& tObj, Args... args)
{
std::cout << "Iteration " << tObj.sec << " ";
return tObj.sec + pf(args...);
}
#endif
int main()
{
NoMoveHardToCopy lVal{10};
std::cout << pf(S{1}, S{2}, lVal) << "\n";
}
Dla wersji pierwszej dostaje z forward i rvalue ref
c
Iteration 1 Iteration 2 Iteration 10 13
Dla wersji drugiej gdzie argumenty sa odbierane przez kopie dostaje
c
cc
Iteration 1 cc
Iteration 2 Iteration 10 13
I pytanie w zasadzie dotyczy wersji z forward ponieważ nie rozumiem jak kompilator przekazuje argument lVal do kolejnych iteracji. Nie widzę wywołania żadnego konstruktora (oprócz domyślnego) a jednak program się wykonuje i zwraca poprawne wyniki. Jak kompilator przekazuje lVal?
W przypadku wersji bez forward widzę poprawnie wywołania konstruktora cc pomiędzy iteracjami gdy obiekt jest przekazywany.