That’s the simplest and most clear way to write it:
template <typename F>
auto invoke_log_return(F&& f)
{
auto result = f();
std::printf(" ...logging here... %s\n", result.foo());
return result;
}
The GCC gets the right (no needless copies or moves) expected result:
s()
in main
prvalue
s()
...logging here... Foo!
lvalue
s(const s&)
...logging here... Foo!
xvalue
s(s&&)
...logging here... Foo!
So if code is clear, have ever the same functionality but is’t optimized to run as much as the competitors does it’s a compiler optimization failure and clang should work it out. That’s the kind of problem that make lot more sense solved in the tool instead the application layer implementation.
https://gcc.godbolt.org/z/50u-hT