1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
#pragma once
#include "globalincs/pstypes.h"
#include <mpark/variant.hpp>
namespace actions {
namespace expression {
namespace detail {
template <typename ToType>
struct implicit_conversion {
template <typename T>
ToType operator()(const T&)
{
throw std::runtime_error("Invalid implicit conversion.");
}
};
template<>
struct implicit_conversion<float> {
inline float operator()(int val) {
return i2fl(val);
}
template <typename T>
float operator()(const T&)
{
throw std::runtime_error("Invalid implicit conversion.");
}
};
} // namespace detail
enum class ValueType
{
Invalid,
Integer,
Float,
Vector,
String,
};
template <typename T>
struct ValueTypeTraits;
template <>
struct ValueTypeTraits<int> {
static constexpr ValueType type = ValueType::Integer;
};
template <>
struct ValueTypeTraits<float> {
static constexpr ValueType type = ValueType::Float;
};
template <>
struct ValueTypeTraits<vec3d> {
static constexpr ValueType type = ValueType::Vector;
};
template <>
struct ValueTypeTraits<SCP_string> {
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 <typename T>
T get() const
{
const auto currentType = getType();
const auto expectedType = ValueTypeTraits<T>::type;
if (currentType == expectedType) {
// No conversion necessary
return mpark::get<T>(m_value);
}
return mpark::visit(detail::implicit_conversion<T>{}, 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<mpark::monostate, int, float, vec3d, SCP_string> m_value;
};
} // namespace expression
} // namespace actions
|