/** * @file common/Any.hpp * @author The ARTIS Development Team * See the AUTHORS or Authors.txt file */ /* * ARTIS - the multimodeling and simulation environment * This file is a part of the ARTIS environment * * Copyright (C) 2013-2019 ULCO http://www.univ-littoral.fr * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef COMMON_ANY_HPP #define COMMON_ANY_HPP #include #include #include #include #include namespace artis { namespace common { class Any { private: struct base { virtual ~base() {} virtual base *clone() const = 0; }; template struct data : base { data(V T::* const &value) : value_(value) {} base *clone() const { return new data(*this); } V T::* value_; }; base *ptr_; public: Any() : ptr_(nullptr) {} template Any(V T::* const &value) : ptr_(new data(value)) {} Any(Any const &other) : ptr_(other.ptr_ ? other.ptr_->clone() : nullptr) {} virtual ~Any() { if (ptr_) { delete ptr_; } } void operator=(Any const &other) { Any(other).swap(*this); } void swap(Any &other) { std::swap(ptr_, other.ptr_); } template V T::* get() const { return dynamic_cast < data * >(ptr_)->value_; } template void get(T *o, V &value) const { data *q = dynamic_cast < data * >(ptr_); if (q) { value = o->*(q->value_); } else { assert(false); } } bool is_null() const { return ptr_ == nullptr; } template void put(T *o, const V &value) { V T::* p = dynamic_cast * >(ptr_)->value_; o->*(p) = value; } template void restore(T *o, const common::Value &value) { if (value.is_type()) { double v; value(v); put(o, v); } else if (value.is_type()) { unsigned int v; value(v); put(o, v); } else if (value.is_type()) { int v; value(v); put(o, v); } else if (value.is_type()) { bool v; value(v); put(o, v); } else if (value.is_type < std::vector < double > > ()) { std::vector v; value(v); put(o, v); } else if (value.is_type < std::vector < unsigned int > > ()) { std::vector v; value(v); put(o, v); } else if (value.is_type < std::vector < int > > ()) { std::vector v; value(v); put(o, v); } else if (value.is_type < std::vector < bool > > ()) { std::vector v; value(v); put(o, v); } else { assert(false); } } template common::Value save(const T *o) const { if (ptr_) { data *q_double = dynamic_cast < data * >(ptr_); if (q_double) { return common::Value(o->*(q_double->value_)); } else { data *q_uint = dynamic_cast < data * >(ptr_); if (q_uint) { return common::Value(o->*(q_uint->value_)); } else { data *q_int = dynamic_cast < data * >(ptr_); if (q_int) { return common::Value(o->*(q_int->value_)); } else { data *q_bool = dynamic_cast < data * >(ptr_); if (q_bool) { return common::Value(o->*(q_bool->value_)); } else { data > *q_double_v = dynamic_cast < data > * > (ptr_); if (q_double_v) { return common::Value(o->*(q_double_v->value_)); } else { data > *q_int_v = dynamic_cast < data > * > (ptr_); if (q_int_v) { return common::Value(o->*(q_int_v->value_)); } else { data > *q_bool_v = dynamic_cast < data > * > (ptr_); if (q_bool_v) { return common::Value(o->*(q_bool_v->value_)); } } } } } } } } assert(false); return common::Value(); } template std::string to_string(const T *o) const { if (ptr_) { data *q_double = dynamic_cast < data * >(ptr_); if (q_double) { return std::to_string(o->*(q_double->value_)); } else { data *q_uint = dynamic_cast < data * >(ptr_); if (q_uint) { return std::to_string(o->*(q_uint->value_)); } else { data *q_int = dynamic_cast < data * >(ptr_); if (q_int) { return std::to_string(o->*(q_int->value_)); } else { data *q_bool = dynamic_cast < data * >(ptr_); if (q_bool) { return o->*(q_bool->value_) ? "true" : "false"; } else { data > *q_double_v = dynamic_cast < data > * > (ptr_); if (q_double_v) { return ""; } else { data > *q_int_v = dynamic_cast < data > * > (ptr_); if (q_int_v) { return ""; } else { data > *q_bool_v = dynamic_cast < data > * > (ptr_); if (q_bool_v) { return ""; } else { return "NA"; } } } } } } } } else { return "NA"; } } }; } } #endif