• basic_calculator.hpp
  • #pragma once 
    #include <unordered_map>
    #include <functional>
    #include <stdexcept>
    
    namespace shunting_yard {
        template<typename T_>
        class basic_calculator {
            private: 
            std::unordered_map<char, std::function<T_(std::pair<T_, T_>)>> calculators; 
            public: 
            // Calculator function declerations. These are the holders for our calculations. 
            // This gives us flexibility to add more functions in the feature and is faster since
            // unordered_map is O(1) access. 
            basic_calculator() : calculators({
                {'+', [](std::pair<T_, T_> operands) -> T_ {
                    return operands.first + operands.second;
                }},
                {'-', [](std::pair<T_, T_> operands) -> T_ {
                    return operands.first - operands.second;
                }},
                {'*', [](std::pair<T_, T_> operands) -> T_ {
                    return operands.first * operands.second; 
                }}, 
                {'/', [](std::pair<T_, T_> operands) -> T_ {
                    if(operands.second == 0) { throw std::invalid_argument("Divison by 0 is requested!"); }
                    return operands.first / operands.second; 
                }}, 
                {'^', [](std::pair<T_, T_> operands) -> T_ {
                    T_ temp = operands.first; 
                    for(int i{}; i < operands.second - 1; i++) {
                        temp *= operands.first; 
                    }
                    return temp; 
                }}
            }) {}
            T_ operator()(char operator_, std::pair<T_, T_> operands) {
                return calculators[operator_](operands); 
            }
            T_ operator()(char operator_, T_ first, T_ second) {
                return calculators[operator_]({first, second}); 
            }
            std::function<T_(std::pair<T_, T_>)>& operator[](char& operator_) {
                return calculators[operator_]; 
            }
            decltype(calculators) GetMap() {
                return calculators;
            }
            bool operator_exists(const std::string& op) {
                return calculators.find(*op.begin()) != calculators.end(); 
            }
        }; 
    }