CGII/framework/include/cgv/reflect/reflection_traits.h
2018-05-17 15:50:03 +02:00

178 lines
7.2 KiB
C++

#pragma once
#include <string>
#include <cgv/type/info/type_name.h>
#include <cgv/type/info/type_id.h>
#include <cgv/type/cond/is_enum.h>
#include <cgv/type/cond/is_abstract.h>
#include <cgv/utils/convert_string.h>
#include "lib_begin.h"
/// the cgv namespace
namespace cgv {
/// in this namespace reflection of types is implemented
namespace reflect {
class CGV_API reflection_handler;
/// different types of reflection traits
enum ReflectionTraitsKind { RTK_STD_TYPE, RTK_SELF_REFLECT, RTK_EXTERNAL_SELF_REFLECT, RTK_STRING };
/// abstract interface for type reflection with basic type management and optional string conversion
struct CGV_API abst_reflection_traits
{
/// provide virtual destructor to allow generation of copies
virtual ~abst_reflection_traits();
/// clone function
virtual abst_reflection_traits* clone() = 0;
/**@name basic type interface */
//@{
/// return the size of the type
virtual unsigned size() const = 0;
/// construct an instance on the heap with the new operator
virtual void* new_instance() const = 0;
/// delete an instance with the delete operator
virtual void delete_instance(void*) const = 0;
/// construct n instances on the heap with the new operator
virtual void* new_instances(unsigned n) const = 0;
/// delete instances with the delete [] operator
virtual void delete_instances(void*) const = 0;
/// return the type id
virtual cgv::type::info::TypeId get_type_id() const = 0;
/// return the type name
virtual const char* get_type_name() const = 0;
//@}
/**@name self reflection through external implementation */
//@{
/// compile information about external implementation
static const bool has_external = false;
/// whether type can be converted to string, defaults to false
virtual bool has_external_implementation() const;
/// call the external implementation
virtual bool external_implementation(reflection_handler& rh, void* member_ptr);
//@}
/**@name self reflection through string conversions */
//@{
/// compile information about string conversions
static const bool has_string = false;
/// whether type can be converted to string, defaults to false
virtual bool has_string_conversions() const;
/// convert a given string value to the reflected type and store in the instance pointer
virtual bool set_from_string(void* instance_ptr, const std::string& str_val);
/// convert given instance into a string value
virtual void get_to_string(const void* instance_ptr, std::string& str_val);
//@}
/**@name additional enum interface */
//@{
/// compile information about enum interface
static const bool has_enum = false;
/// return whether type is an enum type - this is independent of whether enum interface is implemented
virtual bool is_enum_type() const;
/// return whether the traits class implements the enum interface
virtual bool has_enum_interface() const;
/// return the number of enum items
virtual unsigned get_nr_enum_items() const;
/// return the name of the i-th enum item
virtual std::string get_enum_name(unsigned i) const;
/// return the value of the i-th enum item
virtual int get_enum_value(unsigned i) const;
//@}
};
/** \addtogroup detail
* @{
*/
/// implementation of the reflection traits providing type specific interface for variable base class
template <typename T, typename B, bool base_is_abst = cgv::type::cond::is_abstract<B>::value>
struct reflection_traits_impl : public B
{
/// return the size of the type
unsigned size() const { return sizeof(T); }
/// construct an instance on the heap with the new operator
void* new_instance() const { return new T(); }
/// delete an instance with the delete operator
void delete_instance(void* instance_ptr) const { delete static_cast<T*>(instance_ptr); }
/// construct n instances on the heap with the new operator
void* new_instances(unsigned n) const { return new T[n]; }
/// delete instances with the delete [] operator
void delete_instances(void* instance_array) const { delete [] static_cast<T*>(instance_array); }
/// return the type id
cgv::type::info::TypeId get_type_id() const { return cgv::type::info::type_id<T>::get_id(); }
/// return the type name
const char* get_type_name() const { return cgv::type::info::type_name<T>::get_name(); }
/// return whether type is an enum type - this is independent of whether enum interface is implemented
bool is_enum_type() const { return cgv::type::cond::is_enum<T>::value; }
};
/// implementation variant for abstract base classes
template <typename T, typename B>
struct reflection_traits_impl<T,B,true> : public B
{
/// return the size of the type
unsigned size() const { return sizeof(T); }
/// construct an instance on the heap with the new operator
void* new_instance() const { return 0; }
/// delete an instance with the delete operator
void delete_instance(void* instance_ptr) const { delete static_cast<T*>(instance_ptr); }
/// construct n instances on the heap with the new operator
void* new_instances(unsigned n) const { return 0; }
/// delete instances with the delete [] operator
void delete_instances(void* instance_array) const { delete [] static_cast<T*>(instance_array); }
/// return the type id
cgv::type::info::TypeId get_type_id() const { return cgv::type::info::type_id<T>::get_id(); }
/// return the type name
const char* get_type_name() const { return cgv::type::info::type_name<T>::get_name(); }
/// return whether type is an enum type - this is independent of whether enum interface is implemented
bool is_enum_type() const { return cgv::type::cond::is_enum<T>::value; }
};
/// this template allows to distinguish between traits with and without string conversions
template <bool has_str, typename T, typename B>
struct reflection_traits_string_impl : public reflection_traits_impl<T,B>
{
};
/// this is the implementation with string conversions
template <typename T, typename B>
struct reflection_traits_string_impl<true,T,B> : public reflection_traits_impl<T,B>
{
/// compile information about string conversions
static const bool has_string = true;
bool has_string_conversions() const { return true; }
bool set_from_string(void* member_ptr, const std::string& str_val) {
return cgv::utils::from_string(*static_cast<T*>(member_ptr), str_val);
}
void get_to_string(const void* member_ptr, std::string& str_val) {
str_val = cgv::utils::to_string(*static_cast<const T*>(member_ptr));
}
};
/// Default implementation of the reflection traits providing type specific interface
template <typename T, ReflectionTraitsKind KIND = RTK_STRING, bool has_str = true>
struct reflection_traits : public reflection_traits_string_impl<has_str, T, abst_reflection_traits>
{
static const ReflectionTraitsKind kind = KIND;
/// clone function
abst_reflection_traits* clone() { return new reflection_traits<T,KIND,has_str>(); }
};
//! example implementation of the cgv::reflect::get_reflection_traits() function
/*! reimplement for non standard types in order to provide information on how type reflection
is implemented for each type. */
extern CGV_API reflection_traits<bool,RTK_STD_TYPE> get_reflection_traits(const bool&);
/** @}*/
}
}
#include <cgv/config/lib_end.h>