Creating New Named Operators

While there is no straightforward way to add new operators to the language, using the preprocessor, a very close approximation can be achieved.

First, how could we do that? The language doesn't officially allow you to add new operators, but with the help of the preprocessor, we can. The basic idea is to construct a UDT that has an overloaded operator:


    struct sqrt_ { };
    
    // operator used determines precedence
    //                    -v-
    inline double operator * ( sqrt_ const&, double d ) {
        return std::pow( d, 0.5 );
    }

    #define sqrt sqrt_() *
    
// usage

    double d = sqrt 0.5; // operator * ( sqrt_(), 0.5 )

The process is similar for a binary operator:


    class pow_ {
        double lhs; // left argument
    public:
        friend pow_& operator * ( double lhs, pow_& p ) {
            p.lhs = lhs;
            return p;
        }
        double operator * ( double rhs ) const {
            return std::pow( lhs, rhs );
        }
    };

    #define pow  * _pow() *

    double d = 2 pow 8.1; // operator * ( operator * ( 2, pow_() ), 8.1 )

This can be templatized, but I'll leave that to the reader (actually, I have templatized it, where the user puts one line of code to define a new operator, but I haven't yet figured out how to let the user select which operator was used).

We could even add three-operand (and more) operators:


    double mul_div( double a, double b, double c ) {
        return (a * b) / c;
    }
    
    class mul_div_lhs_;
    
    class mul_div_mid_ {
        mutable double mid; // middle argument
    protected:
        mutable double lhs; // left argument
    public:
        double operator * ( double rhs ) const {
            return (lhs * mid) / rhs;
        }
    };

    struct mul_div_lhs_ : mul_div_mid_ {
        friend mul_div_lhs_ const& operator * ( double lhs,
                mul_div_lhs_ const& p )
        {
            p.lhs = lhs;
            return p;
        }
        
        mul_div_mid const& operator * ( double mid ) const {
            this->mid = mid;
            return *this;
        }
    };

    #define mul  * mul_div_lhs_() *
    #define div  *

    double d = 1 mul 2 div 4;
    // operator * ( operator * ( operator * ( 1, _mul_div_lhs() ), 2 ), 4 )

Blargg's C++ Notes