#ifndef SYMBOL_VALUE_HPP #define SYMBOL_VALUE_HPP #include #include #include #include namespace Symbols { class Value { public: using Variant = std::variant; Value() = default; Value(int v) : value_(v) {} Value(double v) : value_(v) {} Value(float v) : value_(v) {} Value(const std::string & v) : value_(v) {} Value(const char * v) : value_(std::string(v)) {} Value(bool v) : value_(v) {} const Variant & get() const { return value_; } Variant & get() { return value_; } template T get() const { return std::get(value_); } // operator+ friend Value operator+(const Value & lhs, const Value & rhs) { return std::visit( [](auto && a, auto && b) -> Value { using A = std::decay_t; using B = std::decay_t; if constexpr ((std::is_arithmetic_v && std::is_arithmetic_v) ) { return Value{ a + b }; } else { throw std::runtime_error("Invalid types for operator+"); } }, lhs.value_, rhs.value_); } // operator== friend bool operator==(const Value & lhs, const Value & rhs) { return lhs.value_ == rhs.value_; } // to_string helper (needed for string + int, etc.) static std::string to_string(const Variant & v) { return std::visit( [](auto && val) -> std::string { using T = std::decay_t; if constexpr (std::is_same_v) { return val ? "true" : "false"; } else if constexpr (std::is_same_v) { return val; } else { return std::to_string(val); } }, v); } static std::string to_string(const Value & val) { return to_string(val.value_); } private: Variant value_; }; } // namespace Symbols #endif // SYMBOL_VALUE_HPP