I was reading up on r-value references and move semantics. Experimenting this with std::function and std::reference_wrapper unfortunately confused me a bit more.
#include <iostream>
#include <string>
#include <string_view>
#include <functional>
class Greeting {
std::string g;
std::function <void(std::string_view)> f;
public:
Greeting(std::string&& _g, std::function<void(std::string_view)>&& _f)
: g(std::move(_g)), f(std::move(_f)){};
void greet() {
f(g);
}
};
struct prefix_g {
std::string g;
public:
prefix_g(const std::string&& _g) : g(std::move(_g)) {}
void operator() (std::string_view s) {
std::cout <<g <<" "<< s << std::endl;
}
};
int main() {
prefix_g eng("Hello");
Greeting g("World",eng);
Greeting g2("World2",std::ref(eng)); // reference wrapper, special
// forwarding for op ()
std::string s3("world3"), s4("world3");
// Greeting g3(std::ref(s3), std::ref(eng)); won't compile; &s3 -> &&s3
// Greeting g3(s3, eng); won't compile lval to rval
// Greeting g4(std::move(s4), std::move(eng)); // compiles, output Hello World2 -> World2 as g is moved?
g.greet(); g2.greet();
Greeting g4(std::move(s4), std::move(eng));
g4.greet();
Greeting g5("world5", std::move(eng)); // UB? move guarantees fn object is
// still valid, ofc, g now gets default
// init to empty
g5.greet();
return 0;
}
- How is it that r-value references to a std::function actually accepts l-values for eg. in case
Greeting g("World",eng)
, a similar l-value wouldn't be acceptable for any other argument (other than templating the constructor and making a universal reference maybe?) ? What actually happens when a std::ref is passed to std::function, ref mentions that merely arguments are forwarded. However if I move the function object itself as the commented out g4 is shown I see the output of g2 which uses std::ref to actually see the move in effect, just printing world2
What happens to the callable object after move, the string itself is moved as seen, however the function would still be valid? (for a different function object of type say, struct
f{void operator()() { //something })
, would this mean that f might be valid after the move?)