I am currently quite puzzled with C++17`s guaranteed RVO and its implications. I understand that for NRVO to kick in, I need to make sure that
to return one and the same instance of an object through all possible return path of the function and
to initialize an associated object with the function call on the call side
Consider a most simple decorated class Widget and I want to allocate a pair of Widgets without copies and then return it
#include<iostream>
#include<utility>
struct Widget {
Widget() { std::cerr << "Default ctor" << std::endl; }
explicit Widget(int i) { std::cerr << "custom ctor" << std::endl; }
Widget(Widget const &) { std::cerr << "copy ctor" << std::endl; }
Widget(Widget &&) { std::cerr << "move ctor" << std::endl; }
Widget &operator=(Widget const &) { std::cerr << "copy assign" << std::endl; }
Widget &operator=(Widget &&) { std::cerr << "move assign" << std::endl; }
int i_;
};
auto foo(){
std::pair<Widget,Widget> w; // default construction
auto &[w1,w2] = w;
// do something with w1 and w2
return w;
}
int main(){
auto f = foo();
}
No copy is made but now I tried to use make_pair
auto foo(){
auto w = std::make_pair<Widget,Widget>({},{}); // Awkward syntax and move construction
auto &[w1,w2] = w;
// do something with w1 and w2
return w;
}
Is this really the only possible alternative if I want to use make_pair? Any why is there move construction involved as compared to the first function?