How to make a wacky math calculator? (Preferably i

2019-05-11 07:29发布

问题:

I would like to know how to do some lower-level thing in C++ that will allow me to do some "wacky" math operations. Specifically my two questions are:

1) How can I define my own math symbol that the compiler will be able to recognizes in my code. In other words, I'm not looking to parse a string from a user, but rather have the compiler recognize this as a new math operation.

   ex:   3 {+} 4   will actually do 3 – 4  etc.

2) How can I define a custom number from an ASCII symbol. For example, define the symbol # to be recognized by the compiler as 18 (i.e. 00010010 in binary).

   ex:   18 {+} # = 18 - 18 = 0

If possible, I would like to be able to do the above two things at the compiler lever. Solutions in C++, Java, C, Python, and Objective-C are fine. Just let me know what language your solution is in. Thanks! :)

回答1:

I said in my comment that this would imply macros in C++; if what you want is not much more complicated than what you show, it should do the trick. Defining operators as macros should work for simple find/replace cases, but it may not be well suited for complex expressions and certain symbols.

Off my head, I think what you want is feasible in Haskell by using infix functions as operators, but it may not be straight-forward for a beginner. Take a look at Lyah and search for infixr. You need a basic knowledge of Haskell though.

Edit with Zeta example, you can run it in ghci:

(<+>) = (-) -- operator definition
(<*>) = (/)

answer = 42
answer <+> 12 -- prints 30
answer <*> 7 -- prints 6.0


回答2:

You can wrap the types into a class, then overload the operators. I came up with a minimal example for "wacky" addition (+ becomes -). But if you want to use PODs you have to use the preprocessor, there is no other way.

#include <iostream>
using namespace std;

template<typename T>
class wacky
{
    T val_;
public:
    wacky(T val = {}): val_(val){};

    // let's define a conversion operator
    template<typename S>
    operator S (){return val_;}

    // we don't need asignment operator and copy ctors

    // stream operators
    friend ostream& operator<<(ostream& os, const wacky& rhs)
    {
        return os << rhs.val_;
    }

    // the += operator
    wacky& operator+=(const wacky& rhs)
    {
        val_ -= rhs.val_; // wacky!
        return *this;
    }

    // and the wacky operator+
    friend wacky operator+(wacky lhs, const wacky& rhs)
    {
        return lhs+=rhs;
    }
};

int main()
{
    wacky<int> a,b;
    a = 10;
    b = 15;

    // a and b behave now like PODs
    // implicit conversions work etc
    double wacky_sum = a + b; 
    cout << wacky_sum << endl; // -5
}