C++ String Non-Member Operator Overloading This is a practice for operator overloading, I am well aware that some of these don't make sense. I am seeking review only on the code/practices, not the purpose.

/* (C) 2017 ZACH HILMAN
 * PROPRIETARY/CONFIDENTIAL. ALL RIGHTS RESERVED
 *
 *
 *
 *
 *
 */
#ifndef COMPUTERSCIENCE_ENHANCED_STRING_H
#define COMPUTERSCIENCE_ENHANCED_STRING_H

#include &lt;string&gt;

/// Remove the first occrance of rhs from lhs.
inline std::string operator-(const std::string&amp; lhs, const std::string&amp; rhs) {
    auto loc = lhs.find(rhs);
    if (loc != -1) return lhs.substr(0, loc) + lhs.substr(loc + rhs.size());
    return std::string();
}

inline std::string&amp; operator-=(std::string&amp; lhs, const std::string&amp; rhs) {
    return lhs = operator-(lhs, rhs);
}

/// Repeat lhs rhs times.
inline std::string operator*(const std::string&amp; lhs, unsigned long rhs) {
    std::string out;
    while (rhs --&gt; 0) out += lhs;
    return out;
}

inline std::string&amp; operator*=(std::string&amp; lhs, unsigned long rhs) {
    return lhs = operator*(lhs, rhs);
}

/// Find the number of times rhs appears in lhs.
inline unsigned long operator/(const std::string&amp; lhs, const std::string&amp; rhs) {
    if (rhs == "") return static_cast&lt;unsigned long&gt;(-1);
    unsigned long out = 0;
    for (unsigned long s_loc = 0, a; s_loc &lt; lhs.size();) {
        if ((a = lhs.find(rhs, s_loc)) != -1) ++out, s_loc = a + 1;
        else break;
    }
    return out;
}

/// Remove all occurances of rhs from lhs.
inline std::string operator%(const std::string&amp; lhs, const std::string&amp; rhs) {
    if (rhs == "") return lhs;
    auto out = lhs;
    std::string::size_type pos;
    while ((pos = out.find(rhs)) != std::string::npos) out = out.replace(pos, rhs.size(), "");
    return out;
}

inline std::string&amp; operator%=(std::string&amp; lhs, const std::string&amp; rhs) {
    return lhs = operator%(lhs, rhs);
}

// Subtract str from STRING_CHARSET (Not done-- will eventually be all ASCII characters).
inline std::string operator~(const std::string&amp; str) {
    static const std::string STRING_CHARSET = "";
    return operator-(STRING_CHARSET, str);
}

// Find the intersection of characters of lhs and rhs.
inline std::string operator&amp;(const std::string&amp; lhs, const std::string&amp; rhs) {
    std::string out;
    for (auto c : lhs) if (rhs.find(c) != std::string::npos) out += c;
    return out;
}

inline std::string&amp; operator&amp;=(std::string&amp; lhs, const std::string&amp; rhs) {
    return lhs = operator&amp;(lhs, rhs);
}

/// Find the union of characters of lhs and rhs.
inline std::string operator|(const std::string&amp; lhs, const std::string&amp; rhs) {
    std::string out;
    for (auto c : lhs) if (out.find(c) == std::string::npos) out += c;
    for (auto r : rhs) if (out.find(r) == std::string::npos) out += r;
    return out;
}

inline std::string&amp; operator|=(std::string&amp; lhs, const std::string&amp; rhs) {
    return lhs = operator|(lhs, rhs);
}

/// Find the XOR of characters of lhs and rhs.
inline std::string operator^(const std::string&amp; lhs, const std::string&amp; rhs) {
    std::string out;
    for (auto c : lhs) if (rhs.find(c) == std::string::npos) out += c;
    for (auto r : rhs) if (lhs.find(r) == std::string::npos) out += r;
    return out;
}

inline std::string&amp; operator^=(std::string&amp; lhs, const std::string&amp; rhs) {
    return lhs = operator^(lhs, rhs);
}

/// Add rhs spaces to the front of lhs.
inline std::string operator&gt;&gt;(const std::string&amp; lhs, unsigned long rhs) {
    return std::string(rhs, ' ') + lhs;
}

inline std::string&amp; operator&gt;&gt;=(std::string&amp; lhs, unsigned long rhs) {
    return lhs = operator&gt;&gt;(lhs, rhs);
}

/// Add rhs spaces to the end of lhs.
inline std::string operator&lt;&lt;(const std::string&amp; lhs, unsigned long rhs) {
    return lhs + std::string(rhs, ' ');
}

inline std::string&amp; operator&lt;&lt;=(std::string&amp; lhs, unsigned long rhs) {
    return lhs = operator&lt;&lt;(lhs, rhs);
}


#endif //COMPUTERSCIENCE_ENHANCED_STRING_H
Style Advice


Do not try to do too much on one line. Constructs such as if ((a = lhs.find(rhs, s_loc)) != -1) ++out, s_loc = a + 1; are difficult to read, difficult to parse and prone to errors. Instead, let each control statement have its own block, and do not abuse the comma operator to do completely unrelated things. For example, the line I mentioned should rather be something like

if ((a = lhs.find(rhs, s_loc)) != -1) {
    ++out;
    s_loc = a + 1;
}


or, even better,

a = lhs.find(rhs, s_loc);
if (a != -1) {
    ++out;
    s_loc = a + 1;
}






Avoid magic numbers. In particular, when checking the result of string::find, check whether the result is equal to std::string::npos, not -1. There even are some places in the code where you are already doing this, so please adopt it for the remaining places as well.
Prefer early return on failure. Concretely, in operator- you return an empty string only after you have checked for and possibly returned a valid result. Although this is quite minor, I would have expected the method to work the other way around, i. e.

if (loc == std::string::npos) {
    return std::string();
}
return lhs.substr(0, loc) + lhs.substr(loc + rhs.size());


which is quite a common pattern.
if (rhs == "") return static_cast&lt;unsigned long&gt;(-1); works but is not expressive. Prefer 

if (rhs.empty()) {
    return std::numeric_limits&lt;unsigned long&gt;::max();
}

while (rhs --&gt; 0) out += lhs; does nothing but obscure what is going on. --&gt; is not an operator in C++, so you should not write it as if it were one. Write while (rhs-- &gt; 0) ...
Remove the typo from the comment to operator-; what currently reads "occrance" should probably be "occurance".


Possible Optimizations

Although generally your code appears to work well, there are some things that you could easily implement to improve performance, mostly to avoid unnecessary copies. 

While it is good practice to implement operators in terms of other operators, the way that you implemented your operation + assignment-operators incurs making additional copies of your input. For example, let's consider operator% and operator%=:

inline std::string operator%(const std::string&amp; lhs, const std::string&amp; rhs) {
    //...
    auto out = lhs;
    //...
    return out;
}

inline std::string&amp; operator%=(std::string&amp; lhs, const std::string&amp; rhs) {

    return lhs = operator%(lhs, rhs);
}


Since operator% does not modify its inputs, it has to make a copy which is then modified and returned. However, operator%= does modify one of its inputs, in this case lhs, so making a copy, modifying it and reassigning it to lhs is unnecessary. Instead, you could approach the problem the other way around: First, implement operator%=, then implement operator% in terms of it: 

inline std::string&amp; operator%=(std::string&amp; lhs, const std::string&amp; rhs) {
    //perform in-place operation on lhs
    return lhs;
}

inline std::string operator%(const std::string&amp; lhs, const std::string&amp; rhs) {
    std::string out = lhs;
    out %= rhs;
    return out;
}