#ifndef INCLUDED_BOBCAT_BINOPS_
#define INCLUDED_BOBCAT_BINOPS_

// This header file requires the separate inclusion of <bobcat/typetrait>
//
//
// The templates in this file were not defined in the namespace FBB to enhance
// their usability. If you want to declare them in a namespace of your own
// include them in your namespace-block, like this:
//  namespace YOUR_NAMESPACE
//  {
//      #include <bobcat/binops>
//  }


template <typename Class>
inline Class operator+(Class &&lhs, Class const &rhs)
{
    return std::move(lhs += rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator+(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp += rhs;
    return tmp;
}
template <typename Class>
inline Class operator&(Class &&lhs, Class const &rhs)
{
    return std::move(lhs &= rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator&(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp &= rhs;
    return tmp;
}
template <typename Class>
inline Class operator|(Class &&lhs, Class const &rhs)
{
    return std::move(lhs |= rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator|(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp |= rhs;
    return tmp;
}
template <typename Class>
inline Class operator^(Class &&lhs, Class const &rhs)
{
    return std::move(lhs ^= rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator^(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp ^= rhs;
    return tmp;
}
template <typename Class>
inline Class operator/(Class &&lhs, Class const &rhs)
{
    return std::move(lhs /= rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator/(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp /= rhs;
    return tmp;
}
template <typename Class>
inline Class operator%(Class &&lhs, Class const &rhs)
{
    return std::move(lhs %= rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator%(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp %= rhs;
    return tmp;
}
template <typename Class>
inline Class operator<<(Class &&lhs, Class const &rhs)
{
    return std::move(lhs <<= rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator<<(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp <<= rhs;
    return tmp;
}
template <typename Class>
inline Class operator>>(Class &&lhs, Class const &rhs)
{
    return std::move(lhs >>= rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator>>(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp >>= rhs;
    return tmp;
}
template <typename Class>
inline Class operator-(Class &&lhs, Class const &rhs)
{
    return std::move(lhs -= rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator-(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp -= rhs;
    return tmp;
}
template <typename Class>
inline Class operator*(Class &&lhs, Class const &rhs)
{
    return std::move(lhs *= rhs);
}
template <typename LHS, typename RHS>
inline typename FBB::Use<LHS, RHS>::type operator*(LHS const &lhs,
                                                   RHS const &rhs)
{
    typename FBB::Use<LHS, RHS>::type tmp(lhs);
    tmp *= rhs;
    return tmp;
}

#endif
