#include <utility> // move
#include <iostream>

using std::move;
using std::ostream;

struct Matrix {
    int d; /* = 0, not yet implemented in gcc-4.7.0 */
    Matrix(int e) : d{e} {}

// construction, copy, assign
    Matrix() = default;
    Matrix(const Matrix&) = default;
    Matrix& operator=(const Matrix&) = default;

// move, move-assign (no no magic in this example)
    Matrix(Matrix&&) = default;
    //Matrix& operator=(Matrix&&) = default;
    Matrix& operator=(Matrix&& o) { swap(*this,o); return *this; };

// friendly STL helper
    friend void swap(Matrix& a, Matrix& b) /* noexcept */ { std::swap(a.d, b.d); }

// imm ops
    void operator+=(const Matrix& o) { d+=o.d; }
    void operator*=(const Matrix& o) { d*=o.d; }

// 2ary ops
    friend Matrix operator+(const Matrix &a, Matrix &&b     ) { b+=a; return move(b); }
    friend Matrix operator+(Matrix &&a,      const Matrix &b) { a+=b; return move(a); }
    friend Matrix operator+(const Matrix &a, Matrix v)        { v+=a; return v; }
    friend Matrix operator+(Matrix &&a,      Matrix &&b)      { a+=b; return move(a); }

    friend Matrix operator*(const Matrix &a, Matrix &&b     ) { b*=a; return move(b); }
    friend Matrix operator*(Matrix &&a,      const Matrix &b) { a*=b; return move(a); }
    friend Matrix operator*(const Matrix &a, Matrix v)        { v*=a; return v; }
    friend Matrix operator*(Matrix &&a,      Matrix &&b)      { a*=b; return move(a); }

// demo helper
    friend ostream& operator<<(ostream&os, const Matrix& m)
    { return os << m.d; }

};


int main()
{
    Matrix a{2},b{3},c{4},d{5};
    Matrix x = a*b + c*d; // 2*3+4*5 = 6+20 = 26

    std::cout << x << std::endl;
}
