If a class supports copy construction and if it offers binary assignment operators (i.e., it offers members of the form operator@=), then the matching binary operators can all be implemented identically. The move-aware Class &operator@(Class &&lhs, Class const &rhs) is easily implemented in terms of operator@= (note that the class itself doesn't have to be `move-aware' to define this function). The move-aware binary operator one requires a one line implementation, and as its implementation never changes it could safely be defined inline:
Class operator@(Class &&lhs, Class const &rhs)
{
    return std::move(std::move(lhs) @= rhs);
}
        
    The traditional binary operator can be implemented using its standard
form:
        
Class operator@(Class const &lhs, Class const &rhs)
{
    Class tmp(lhs);
    tmp @= rhs;
    return tmp;
}
        
    The implementation in bobcat/binops is slightly more complex as it
allows from lhs or rhs promotions.
As the binary operators can all be implemented alike their definitions are perfectly suited for templates: A class offering a particular operator@= then automatically also offers the matching binary operators after including bobcat/binops. Since the binary function templates are not instantiated until used their definitions can be processed by the compiler even if a class implements only a subset of the available binary assignment operators.
The binary operator functions templates in bobcat/binops are not implemented in a particular namespace. This allows sources to include bobcat/binops in multiple namespaces.
If bobcat/binops is to be used in multiple namespaces then the include safeguard (using the identifier INCLUDED_BOBCAT_BINOPS_) must be suppressed between inclusions of bobcat/binops in different namespaces.
E.g., to make the binary operator function templates available in a source file using the namespace FBB and in a source file using the default namespace the following scheme can be used:
#include <utility>              // ensure std::move is available
#include <bobcat/typetrait>     // required by binops
namespace MY_NAMESPACE
{
    #include <bobcat/binops>    // binary operators available in MY_NAMESPACE
}
#undef INCLUDED_BOBCAT_BINOPS_  // suppress the include guard
#include <bobcat/binops>        // read binops again so the binary
                                // operators can be used in the
                                // default namespace as well
    
Move-aware operators, using temporary objects for its left-hand side operands:
`Traditional' operators, using lvalue references to constant objects for its left-hand side operands:
#include <iostream>
#include <utility>
#include "../../typetrait/typetrait"
#include "../binops"
class Demo
{
    friend std::ostream &operator<<(std::ostream &out, Demo const &demo);
    int d_value;
    public:
        Demo(int value = 0)
        :
            d_value(value)
        {}
        Demo(Demo const &other)
        :
            d_value(other.d_value)
        {
            std::cout << "Demo CC called\n";
        }
        Demo &operator+=(Demo const &rhs)
        {
            d_value += rhs.d_value;
            return *this;
        }
};
std::ostream &operator<<(std::ostream &out, Demo const &demo)
{
    return out << demo.d_value;
}
using namespace std;
int main()
{
    Demo four(4);
    Demo five(5);
    cout << four + five << '\n' <<
            four + 5 << '\n' <<
            4  + five << '\n';
}