#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) {}
    
    template <typename T1>
    fast_arg(T1 &&val)
    : lval_(nullptr), rval_(nullptr)
    {
        static T temp(std::forward<T1>(val));
        rval_ = &temp;
    }
    
    void copy_to(T &target)
    {
        if (lval_) target = *lval_;
        else       target = std::move(*rval_);
    }
    
    T create_as_copy()
    {
        if (lval_) return *lval_;
        else       return std::move(*rval_);
    }
    
private:
    const T *lval_;
    T *rval_;
};

class logged_creation
{
public:
    logged_creation() {std::cout << "def ctor\n";}
    logged_creation(int) {std::cout << "int 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)
    {
        auto v = val.create_as_copy();
    }
};

int main()
{
    foo<logged_creation> f;
    std::cout << "LValue:\n";
    logged_creation i;
    f.func(i);
    std::cout << "RValue:\n";
    f.func(logged_creation());
    std::cout << "Converted Temporary:\n";
    f.func(42);
}
