#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());
}
