2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-21 02:52:18 +00:00
Files
fiber/boost/reflection/parameter.hpp
Oliver Kowalke 39ec793737 initial checkin
2011-02-09 18:41:35 +01:00

177 lines
5.4 KiB
C++

/*
* Boost.Reflection / paramater map (store parameter information for calls)
*
* (C) Copyright Mariano G. Consoni 2008
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/ for latest version.
*/
#ifndef BOOST_REFLECTION_PARAMETER_HPP
#define BOOST_REFLECTION_PARAMETER_HPP
#include <boost/extension/impl/typeinfo.hpp>
#include <exception>
#include <map>
#include <vector>
namespace boost { namespace reflections {
using extensions::type_info_handler;
class conversion_not_found_exception : public std::exception {
public:
virtual const char* what() {
return "Cannot convert types";
}
};
/** \brief A container for a single item - similar to boost::any.
*
* The primary difference between generic_parameter and boost::any
* is that a generic_parameter can be declared to be convertible
* to arbitrary types, in addition to the base type that it holds.
* This allows an object to also be accessible through pointers to
* its base types, for example.
*/
template <class TypeInfo = extensions::default_type_info>
class generic_parameter {
public:
typedef void (*FunctionPtr)();
/** The destructor cleans up the converters contained
* in this generic_parameter.
*/
virtual ~generic_parameter() {
for (typename std::map<TypeInfo, basic_converter*>::iterator
it = converters_.begin();
it != converters_.end(); ++it) {
delete it->second;
}
}
/** Return the TypeInfo for the primary type of this generic_parameter.
*/
virtual TypeInfo type() const = 0;
/** \brief Returns true if the parameter can convert to T.
*
* Given a type T, this function returns true if the generic_parameter
* can convert its value to T.
* \tparam T The type to check for conversions for.
* \returns true if the conversion is possible.
*/
template <class T>
bool can_cast() const {
TypeInfo i = type_info_handler<TypeInfo, T>::get_class_type();
return (converters_.find(i) != converters_.end());
}
/** \brief Returns a type S, converted from the type in the parameter.
*
* This will attempt to convert the generic_parameter to type T.
* If it fails, it will throw an exception. To avoid the exception,
* the can_cast function can be called first.
* \tparam T
* \returns A value of T that was converted from the generic_parameter.
* \pre can_cast<T>() == true
* \post None.
*/
template <class T>
T cast() const {
T dest;
TypeInfo i = type_info_handler<TypeInfo, T>::get_class_type();
typename std::map<TypeInfo, basic_converter*>::const_iterator it =
converters_.find(i);
if (it != converters_.end()) {
it->second->convert(value_, reinterpret_cast<void*>(&dest));
return dest;
}
throw conversion_not_found_exception();
}
/** \brief Another form of cast.
*
* Identical to T cast(), but takes a pointer to T instead.
*/
template <class T>
void cast(T* dest) {
*dest = cast<T>();
}
protected:
generic_parameter(void* value) : value_(value) {
}
class basic_converter {
public:
virtual void convert(void* src, void* dest) const = 0;
virtual ~basic_converter() {}
};
std::map<TypeInfo, basic_converter*> converters_;
private:
void* value_;
};
template <class T, class TypeInfo = extensions::default_type_info>
class parameter : public generic_parameter<TypeInfo> {
public:
template <class A, class B>
friend class basic_parameter_map;
virtual TypeInfo type() const {
return reflections::type_info_handler<TypeInfo, T>::get_class_type();
}
explicit parameter(T value)
: generic_parameter<TypeInfo>(reinterpret_cast<void*>(&value_)),
value_(value) {
// Add converter for current type.
generic_parameter<TypeInfo>::converters_.insert
(std::make_pair(reflections::type_info_handler<TypeInfo, T>
::get_class_type(),
new default_converter<T>()));
}
template <class S>
void converts_to_with_func(void (*convert_func)(T*, S*)) {
generic_parameter<TypeInfo>::converters_.insert
(std::make_pair(reflections::type_info_handler<TypeInfo, S>
::get_class_type(),
new specialized_converter<S>(convert_func)));
}
template <class S>
void converts_to() {
generic_parameter<TypeInfo>::converters_.insert
(std::make_pair(reflections::type_info_handler<TypeInfo, S>
::get_class_type(),
new default_converter<S>()));
}
private:
template <class S>
class default_converter :
public generic_parameter<TypeInfo>::basic_converter {
public:
virtual void convert(void* val, void* dest) const {
S* s = reinterpret_cast<S*>(dest);
*s = static_cast<S>(*reinterpret_cast<T*>(val));
}
};
template <class S>
class specialized_converter :
public generic_parameter<TypeInfo>::basic_converter {
public:
explicit specialized_converter(void (*convert_function)(T*, S*))
: convert_function_(convert_function) {
}
virtual void convert(void* val, void* dest) const {
S* s = reinterpret_cast<S*>(dest);
(*convert_function_)(reinterpret_cast<T*>(val), s);
}
private:
void (*convert_function_)(T*, S*);
};
T value_;
};
}
}
#endif // BOOST_REFLECTION_PARAMETER_HPP