/** * @file artis/kernel/Any.hpp * @author See the AUTHORS file */ /* * Copyright (C) 2012-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 __ARTIS_KERNEL_ANY_HPP #define __ARTIS_KERNEL_ANY_HPP #include #include #include #include #include namespace artis { namespace kernel { enum ValueTypeID { DOUBLE, INT, BOOL, DOUBLE_VECTOR, INT_VECTOR, BOOL_VECTOR, STRING, USER }; // template < typename H, typename T > // struct typelist // { // typedef H head; // typedef T tail; // }; // struct null_typelist // { }; // template < typename Fun > // struct cons; // template < typename T1 > // struct cons < void (*)(T1)> // { // typedef typelist < T1, null_typelist > type; // }; // template < typename T1, typename T2 > // struct cons < void (*)(T1, T2)> // { // typedef typelist < T1, typelist < T2, null_typelist > > type; // }; // template < typename T1, typename T2, typename T3 > // struct cons < void (*)(T1, T2, T3)> // { // typedef typelist < T1, typelist < T2, typelist < T3, // null_typelist > > > type; // }; // #define TYPELIST(a) cons < void (*)a >::type // typedef TYPELIST((double, int, bool)) value_types; 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_; /* template < typename V > friend struct ValueType; */ 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_; } bool is_null() const { return ptr_ == nullptr; } template void put(T* o, const V& value) { V T::* p = dynamic_cast < data* >(ptr_)->value_; o->*(p) = value; } template void restore(T* o, const context::Value& value) { if (value.is_type()) { double v; value.get_content(v); put(o, v); } else if (value.is_type()) { int v; value.get_content(v); put(o, v); } else if (value.is_type()) { bool v; value.get_content(v); put(o, v); } else if (value.is_type >()) { std::vector v; value.get_content(v); put(o, v); } else if (value.is_type >()) { std::vector v; value.get_content(v); put(o, v); } else if (value.is_type >()) { std::vector v; value.get_content(v); put(o, v); } else { assert(false); } } template context::Value save(const T* o) const { if (ptr_) { data* q_double = dynamic_cast < data* >(ptr_); if (q_double) { return context::Value(o->*(q_double->value_)); } else { data* q_int = dynamic_cast < data* >(ptr_); if (q_int) { return context::Value(o->*(q_int->value_)); } else { data* q_bool = dynamic_cast < data* >(ptr_); if (q_bool) { return context::Value(o->*(q_bool->value_)); } else { data >* q_double_v = dynamic_cast < data >* >(ptr_); if (q_double_v) { return context::Value(o->*(q_double_v->value_)); } else { data >* q_int_v = dynamic_cast < data >* >(ptr_); if (q_int_v) { return context::Value(o->*(q_int_v->value_)); } else { data >* q_bool_v = dynamic_cast < data >* >(ptr_); if (q_bool_v) { return context::Value( o->*(q_bool_v->value_)); } } } } } } } assert(false); return context::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_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"; } } }; // template < typename C, // typename T, // typename Seq = std::make_integer_sequence // < int, std::tuple_size < T >::value > > // struct TupleIterator; // template < typename C, // typename T, // int... S > // struct TupleIterator < C, T, std::integer_sequence < int, S... > > // { // TupleIterator(C caller, const T& val) // { result = std::make_tuple(caller(std::get < S >(val))...); } // std::tuple < context::Value, context::Value, context::Value > result; // }; // template < typename C, typename T > // TupleIterator < C, T > tuple_iterator(C caller, const T& val) // { // return TupleIterator < C, T >(caller, val); // } // template < typename T > // struct ToValueCaller // { // ToValueCaller(const Any& any, const T* o) : _any(any), _object(o) // { } // template < typename Z > // context::Value operator()(const Z& data) const // { return data.to_value(_any, _object); } // const Any& _any; // const T* _object; // }; // template < typename V > // struct ValueType // { // template < typename T > // context::Value to_value(const Any& any, const T* o) const // { // Any::data < T, V >* q = dynamic_cast < Any::data < T, V >* >(any.ptr_); // if (q) { // return context::Value(o->*(q->value_)); // } else { // return context::Value(); // } // } // }; // template < typename Tuple, typename F, size_t... Is > // constexpr auto apply_impl(Tuple t, F f, std::index_sequence < Is... >) // { return f(std::get < Is >(t)...); } // template < typename Tuple, typename F > // constexpr auto apply(Tuple t, F f) // { return apply_impl(t, f, std::make_index_sequence < // std::tuple_size < Tuple >{}>{}); } // struct find_not_null_value // { // context::Value operator()(const context::Value& left, // const context::Value& right) const; // }; // template < typename T > // static context::Value to_value(const Any& any, const T* o) // { // auto value_types = // std::make_tuple(ValueType < double >(), // ValueType < int >(), // ValueType < bool >()); // auto list = tuple_iterator(ToValueCaller < T >(any, o), value_types); // auto result = apply(list.result, find_not_null_value{}); // std::cout << result.to_string() << std::endl; // assert(false); // } } } #endif