/** * @file artis/kernel/Any.hpp * @author See the AUTHORS file */ /* * Copyright (C) 2012-2017 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 __ARTIS_KERNEL_ANY_HPP #define __ARTIS_KERNEL_ANY_HPP #include #include #include namespace artis { namespace kernel { enum ValueType { DOUBLE, INT, BOOL }; class Any { private: struct base { virtual ~base() { } virtual base* clone() const = 0; }; template < typename T, typename V > struct data : base { data(V T::* const& value) : value_(value) { } base* clone() const { return new data < T, V >(*this); } V T::* value_; }; base* ptr_; public: Any() : ptr_(nullptr) { } template < typename T, typename V > Any(V T::* const& value) : ptr_(new data < T, V >(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 < typename T, typename V > V T::* get() const { return dynamic_cast < data < T, V >* >(ptr_)->value_; } bool is_null() const { return ptr_ == nullptr; } template < typename T, typename V > void put(T* o, const V& value ) { V T::* p = dynamic_cast < data < T, V >* >(ptr_)->value_; o->*(p) = value; } template < typename T > void restore(T* o, const context::Value& value) { if (value.is_double()) { double v; value.get_content(v); put(o, v); } else if (value.is_int()) { int v; value.get_content(v); put(o, v); } else if (value.is_bool()) { bool v; value.get_content(v); put(o, v); } else if (value.is_double_vector()) { std::vector < double > v; value.get_content(v); put(o, v); } else if (value.is_int_vector()) { std::vector < int > v; value.get_content(v); put(o, v); } else if (value.is_bool_vector()) { std::vector < bool > v; value.get_content(v); put(o, v); } else { assert(false); } } template < typename T > context::Value save(const T* o) const { if (ptr_) { data < T, double >* q_double = dynamic_cast < data < T, double >* >(ptr_); if (q_double) { return context::Value(o->*(q_double->value_)); } else { data < T, int >* q_int = dynamic_cast < data < T, int >* >(ptr_); if (q_int) { return context::Value(o->*(q_int->value_)); } else { data < T, bool >* q_bool = dynamic_cast < data < T, bool >* >(ptr_); if (q_bool) { return context::Value(o->*(q_bool->value_)); } else { data < T, std::vector < double > >* q_double_v = dynamic_cast < data < T, std::vector < double > >* >(ptr_); if (q_double_v) { return context::Value(o->*(q_double_v->value_)); } else { data < T, std::vector < int > >* q_int_v = dynamic_cast < data < T, std::vector < int > >* >(ptr_); if (q_int_v) { return context::Value(o->*(q_int_v->value_)); } else { data < T, std::vector < bool > >* q_bool_v = dynamic_cast < data < T, std::vector < bool > >* >(ptr_); if (q_bool_v) { return context::Value( o->*(q_bool_v->value_)); } } } } } } } assert(false); } template < typename T > std::string to_string(const T* o) const { if (ptr_) { data < T, double >* q_double = dynamic_cast < data < T, double >* >(ptr_); if (q_double) { return std::to_string(o->*(q_double->value_)); } else { data < T, int >* q_int = dynamic_cast < data < T, int >* >(ptr_); if (q_int) { return std::to_string(o->*(q_int->value_)); } else { data < T, bool >* q_bool = dynamic_cast < data < T, bool >* >(ptr_); if (q_bool) { return o->*(q_bool->value_) ? "true": "false"; } else { data < T, std::vector < double > >* q_double_v = dynamic_cast < data < T, std::vector < double > >* >(ptr_); if (q_double_v) { return ""; } else { data < T, std::vector < int > >* q_int_v = dynamic_cast < data < T, std::vector < int > >* >(ptr_); if (q_int_v) { return ""; } else { data < T, std::vector < bool > >* q_bool_v = dynamic_cast < data < T, std::vector < bool > >* >(ptr_); if (q_bool_v) { return ""; } else { return "NA"; } } } } } } } else { return "NA"; } } }; } } #endif