Dec 1, 2014

[C++11] decltype with X-value expression

Code often shows e.g:
T& operator=(T&& rhs)
{
 var_1 = std::move(rhs.var_1);
}
What would be the difference between:
var_1 = std::move(rhs.var_1);
//and
var_1 = std::move(rhs).var_1;
Now having pr-value, x-value, g-value etc. http://en.cppreference.com/w/cpp/language/value_category

  1. r-value reference is r-value. like c.v, r-value object's data member is
    r-value. 
  2. decltype(expression) will consider
  • T l-value -> T& 
  • T x-value -> T&&
  • otherwise, T

decltype((std::move(x).var_1)) tmp_1 = 42;
has the type of type_var_1&&
decltype((Type{}.var_1)) tmp_1; //Type{} as p-rvalue
has the type of var_1 :-| code test below:
#include <iostream>
#include <utility>

using namespace std;

struct FunObj
{
    int a{0};
    int* ptr{new int{42}};
 
    auto fin()&&
    {
        cout << "~fin~" << endl;
    }

    auto& operator=(FunObj&& rhs)
    {
        cout << "in FunObj move assign op" << endl;
        a = rhs.a;
        ptr = rhs.ptr;
        rhs.ptr = nullptr;
        return *this;
    }
 
    ~FunObj()
    {
        cout << "~FunObj Outer " << endl;
        if (ptr != nullptr)
        {
            cout << "~FunObj Inner" << endl;
            delete ptr;
        }
    }
};


int main()
{
    FunObj fo;
    int i_tmp{42};
    /* won't compile due to r-value referece bind to l-value
    decltype((std::move(fo).a)) i_1 = i_tmp;
    */
    // int&&
    decltype((std::move(fo).a)) i_1 = 42;

    // int
    decltype((FunObj{}.a)) i_2;

    // int&&
    decltype((declval<FunObj>().a)) i_3 = 42;

    /*
     * xvalue:
     * http://stackoverflow.com/a/11661184
     * http://en.cppreference.com/w/cpp/language/decltype
     * http://en.cppreference.com/w/cpp/language/value_category
     */
    struct LocalType
    {
        FunObj fo_{};
        LocalType()=default;
        LocalType(LocalType&& lt)
        {
            // r-value reference bind to x-value
            fo_ = std::move(lt).fo_;
            // equal to :
            // fo_ = std::move(lt.fo_);
        }
    };

    LocalType lt_1;
    LocalType lt_2 = std::move(lt_1);

    // won't compile in clang 3.5.0
    // however, it compiles in 4.8.3 20140627 ~~
    // fo.fin();
    std::move(fo).fin();
    FunObj{}.fin();
}

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.