rvalue と lvalue の理解を深める

なんとなく分かっていなかったので、改めて復習。
書かないとなかなか覚えないですね…。

[ソース]

struct X{};

void
lvalue_f(X lvalue){}

void
lvalue_reference_f(X& lr){}

void
const_lvalue_reference_f(X const& clr){}

void
rvalue_reference_f(X&& rr){}


template<typename T>
void
T_lvalue_f(T lvalue){}

template<typename T>
void
T_lvalue_reference_f(T& lr){}

template<typename T>
void
T_const_lvalue_reference_f(T const& clr){}

template<typename T>
void
T_rvalue_reference_f(T&& rr){}


int
main(){
    // lvalue
    X x;

    // rvalue
    X();
    
    // lvalue ← rvalue
    X lv = X();                        // OK
    
    // lvaleu reference ← lvalue
    X& lr1 = lv;                       // OK

    // lvaleu reference ← rvalue
//    X& lr2 = X();                    // NG
    
    // const lvaleu reference ← rvalue
    X const& clr = X();                // OK    ※
    
    // rvalue reference ← lvalue
//    X&& rr1 = lv;                    // NG
    
    // rvalue reference ← rvalue
    X&& rr2 = X();                     // OK
    

    // lvalue ← lvalue
    lvalue_f(lv);                      // OK
    
    // lvalue ← rvalue
    lvalue_f(X());                     // OK
    
    // lvalue reference ← lvalue
    lvalue_reference_f(lv);            // OK
    
    // lvalue reference ← rvalue
//    lvalue_reference_f(X());         // NG

    // const lvalue reference ← lvalue
    const_lvalue_reference_f(lv);         // OK
    
    // const lvalue reference ← rvalue
    const_lvalue_reference_f(X());        // OK
    
    // rvalue reference ← lvalue
//    rvalue_reference_f(lv);             // NG
    
    // lvalue reference ← rvalue
    rvalue_reference_f(X());              // OK


    // lvalue ← lvalue
    T_lvalue_f(lv);                       // OK
    
    // lvalue ← rvalue
    T_lvalue_f(X());                      // OK
    
    // lvalue reference ← lvalue
    T_lvalue_reference_f(lv);             // OK
    
    // lvalue reference ← rvalue
//    T_lvalue_reference_f(X());            // NG

    // const lvalue reference ← lvalue
    T_const_lvalue_reference_f(lv);         // OK
    
    // const lvalue reference ← rvalue
    T_const_lvalue_reference_f(X());        // OK
    
    // rvalue reference ← lvalue
    T_rvalue_reference_f(lv);               // OK    ※
    
    // lvalue reference ← rvalue
    T_rvalue_reference_f(X());              // OK

    return 0;
}

肝なのは、const な lvalue reference だと rvalue が受け取れるのと、template T&& の場合は lvalue も受け取ることができる事ですかね。
(T&& が X& になる)
まだまだ、理解が足りないのでどんどん使っていきたいところです。