#include <iostream>
template <typename T>
class fast_arg
{
public:
fast_arg(const T & val)
: lval_(&val), rval_(nullptr) {}
fast_arg(T &&val)
: lval_(nullptr), rval_(&val) {}
void copy_to(T &target)
{
if (lval_) target = *lval_;
else target = std::move(*rval_);
}
private:
const T *lval_;
T *rval_;
};
class logged_creation
{
public:
logged_creation() {std::cout << "def ctor\n";}
logged_creation(const logged_creation &) {std::cout << "copy ctor\n";}
logged_creation(logged_creation &&) {std::cout << "move ctor\n";}
logged_creation& operator = (const logged_creation &) {std::cout << "copy assignment\n";}
logged_creation& operator = (logged_creation &&) {std::cout << "move assignment\n";}
};
template <typename T>
class foo
{
public:
void func(fast_arg<T> val)
{
T v;
val.copy_to(v);
}
};
int main()
{
foo<logged_creation> f;
std::cout << "LValue:\n";
logged_creation i;
f.func(i);
std::cout << "RValue:\n";
f.func(logged_creation());
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmNsYXNzIGZhc3RfYXJnCnsKcHVibGljOgogICAgZmFzdF9hcmcoY29uc3QgVCAmIHZhbCkKICAgIDogbHZhbF8oJnZhbCksIHJ2YWxfKG51bGxwdHIpIHt9CiAgICBmYXN0X2FyZyhUICYmdmFsKQogICAgOiBsdmFsXyhudWxscHRyKSwgcnZhbF8oJnZhbCkge30KICAgIAogICAgdm9pZCBjb3B5X3RvKFQgJnRhcmdldCkKICAgIHsKICAgICAgICBpZiAobHZhbF8pIHRhcmdldCA9ICpsdmFsXzsKICAgICAgICBlbHNlICAgICAgIHRhcmdldCA9IHN0ZDo6bW92ZSgqcnZhbF8pOwogICAgfQogICAgCnByaXZhdGU6CiAgICBjb25zdCBUICpsdmFsXzsKICAgIFQgKnJ2YWxfOwp9OwoKY2xhc3MgbG9nZ2VkX2NyZWF0aW9uCnsKcHVibGljOgogICAgbG9nZ2VkX2NyZWF0aW9uKCkge3N0ZDo6Y291dCA8PCAiZGVmIGN0b3JcbiI7fQogICAgbG9nZ2VkX2NyZWF0aW9uKGNvbnN0IGxvZ2dlZF9jcmVhdGlvbiAmKSB7c3RkOjpjb3V0IDw8ICJjb3B5IGN0b3JcbiI7fQogICAgbG9nZ2VkX2NyZWF0aW9uKGxvZ2dlZF9jcmVhdGlvbiAmJikge3N0ZDo6Y291dCA8PCAibW92ZSBjdG9yXG4iO30KICAgIGxvZ2dlZF9jcmVhdGlvbiYgb3BlcmF0b3IgPSAoY29uc3QgbG9nZ2VkX2NyZWF0aW9uICYpIHtzdGQ6OmNvdXQgPDwgImNvcHkgYXNzaWdubWVudFxuIjt9CiAgICBsb2dnZWRfY3JlYXRpb24mIG9wZXJhdG9yID0gKGxvZ2dlZF9jcmVhdGlvbiAmJikge3N0ZDo6Y291dCA8PCAibW92ZSBhc3NpZ25tZW50XG4iO30KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpjbGFzcyBmb28KewpwdWJsaWM6CiAgICB2b2lkIGZ1bmMoZmFzdF9hcmc8VD4gdmFsKQogICAgewogICAgICAgIFQgdjsKICAgICAgICB2YWwuY29weV90byh2KTsKICAgIH0KfTsKCmludCBtYWluKCkKewogICAgZm9vPGxvZ2dlZF9jcmVhdGlvbj4gZjsKICAgIHN0ZDo6Y291dCA8PCAiTFZhbHVlOlxuIjsKICAgIGxvZ2dlZF9jcmVhdGlvbiBpOwogICAgZi5mdW5jKGkpOwogICAgc3RkOjpjb3V0IDw8ICJSVmFsdWU6XG4iOwogICAgZi5mdW5jKGxvZ2dlZF9jcmVhdGlvbigpKTsKfQo=