/**
* @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