#pragma once #include "globalincs/pstypes.h" #include namespace actions { namespace expression { namespace detail { template struct implicit_conversion { template ToType operator()(const T&) { throw std::runtime_error("Invalid implicit conversion."); } }; template<> struct implicit_conversion { inline float operator()(int val) { return i2fl(val); } template float operator()(const T&) { throw std::runtime_error("Invalid implicit conversion."); } }; } // namespace detail enum class ValueType { Invalid, Integer, Float, Vector, String, }; template struct ValueTypeTraits; template <> struct ValueTypeTraits { static constexpr ValueType type = ValueType::Integer; }; template <> struct ValueTypeTraits { static constexpr ValueType type = ValueType::Float; }; template <> struct ValueTypeTraits { static constexpr ValueType type = ValueType::Vector; }; template <> struct ValueTypeTraits { static constexpr ValueType type = ValueType::String; }; class Value { public: Value() = default; explicit Value(int val); explicit Value(float val); explicit Value(const vec3d& val); explicit Value(SCP_string val); ValueType getType() const; int getInteger() const; float getFloat() const; vec3d getVector() const; SCP_string getIdentifier() const; template T get() const { const auto currentType = getType(); const auto expectedType = ValueTypeTraits::type; if (currentType == expectedType) { // No conversion necessary return mpark::get(m_value); } return mpark::visit(detail::implicit_conversion{}, m_value); } friend bool operator==(const Value& lhs, const Value& rhs); friend bool operator!=(const Value& lhs, const Value& rhs); friend std::ostream& operator<<(std::ostream& os, const Value& value); private: mpark::variant m_value; }; } // namespace expression } // namespace actions