From 408543645a7df8290b3a3186189295a6e0637002 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Thu, 11 Jun 2009 16:06:09 +0000 Subject: [PATCH] Revert to r133. Try again --- CMakeLists.txt | 2 +- {dispatch_engine => boxedcpp}/CMakeLists.txt | 0 {dispatch_engine => boxedcpp}/bootstrap.hpp | 0 .../bootstrap_stl.hpp | 0 {dispatch_engine => boxedcpp}/boxed_value.hpp | 0 {dispatch_engine => boxedcpp}/boxedcpp.hpp | 0 .../proxy_constructors.hpp | 0 .../proxy_functions.hpp | 0 .../register_function.hpp | 0 {dispatch_engine => boxedcpp}/test.cpp | 0 {dispatch_engine => boxedcpp}/type_info.hpp | 0 {dispatch_engine => boxedcpp}/unittest.cpp | 0 dispatchkit/dispatch_engine/CMakeLists.txt | 23 + dispatchkit/dispatch_engine/bootstrap.hpp | 522 ++++++++++++++++++ dispatchkit/dispatch_engine/bootstrap_stl.hpp | 82 +++ dispatchkit/dispatch_engine/boxed_value.hpp | 385 +++++++++++++ dispatchkit/dispatch_engine/boxedcpp.hpp | 209 +++++++ .../dispatch_engine/proxy_constructors.hpp | 46 ++ .../dispatch_engine/proxy_functions.hpp | 228 ++++++++ .../dispatch_engine/register_function.hpp | 35 ++ dispatchkit/dispatch_engine/test.cpp | 187 +++++++ dispatchkit/dispatch_engine/type_info.hpp | 80 +++ dispatchkit/dispatch_engine/unittest.cpp | 17 + 23 files changed, 1815 insertions(+), 1 deletion(-) rename {dispatch_engine => boxedcpp}/CMakeLists.txt (100%) rename {dispatch_engine => boxedcpp}/bootstrap.hpp (100%) rename {dispatch_engine => boxedcpp}/bootstrap_stl.hpp (100%) rename {dispatch_engine => boxedcpp}/boxed_value.hpp (100%) rename {dispatch_engine => boxedcpp}/boxedcpp.hpp (100%) rename {dispatch_engine => boxedcpp}/proxy_constructors.hpp (100%) rename {dispatch_engine => boxedcpp}/proxy_functions.hpp (100%) rename {dispatch_engine => boxedcpp}/register_function.hpp (100%) rename {dispatch_engine => boxedcpp}/test.cpp (100%) rename {dispatch_engine => boxedcpp}/type_info.hpp (100%) rename {dispatch_engine => boxedcpp}/unittest.cpp (100%) create mode 100644 dispatchkit/dispatch_engine/CMakeLists.txt create mode 100644 dispatchkit/dispatch_engine/bootstrap.hpp create mode 100644 dispatchkit/dispatch_engine/bootstrap_stl.hpp create mode 100644 dispatchkit/dispatch_engine/boxed_value.hpp create mode 100644 dispatchkit/dispatch_engine/boxedcpp.hpp create mode 100644 dispatchkit/dispatch_engine/proxy_constructors.hpp create mode 100644 dispatchkit/dispatch_engine/proxy_functions.hpp create mode 100644 dispatchkit/dispatch_engine/register_function.hpp create mode 100644 dispatchkit/dispatch_engine/test.cpp create mode 100644 dispatchkit/dispatch_engine/type_info.hpp create mode 100644 dispatchkit/dispatch_engine/unittest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 661e75c5..501f4647 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,6 @@ SET (CMAKE_CXX_FLAGS_GDB " -Wall -ggdb") include_directories(boxedcpp) add_subdirectory(langkit bin) -add_subdirectory(dispatchkit bin) +add_subdirectory(boxedcpp bin) add_subdirectory(wesley bin) \ No newline at end of file diff --git a/dispatch_engine/CMakeLists.txt b/boxedcpp/CMakeLists.txt similarity index 100% rename from dispatch_engine/CMakeLists.txt rename to boxedcpp/CMakeLists.txt diff --git a/dispatch_engine/bootstrap.hpp b/boxedcpp/bootstrap.hpp similarity index 100% rename from dispatch_engine/bootstrap.hpp rename to boxedcpp/bootstrap.hpp diff --git a/dispatch_engine/bootstrap_stl.hpp b/boxedcpp/bootstrap_stl.hpp similarity index 100% rename from dispatch_engine/bootstrap_stl.hpp rename to boxedcpp/bootstrap_stl.hpp diff --git a/dispatch_engine/boxed_value.hpp b/boxedcpp/boxed_value.hpp similarity index 100% rename from dispatch_engine/boxed_value.hpp rename to boxedcpp/boxed_value.hpp diff --git a/dispatch_engine/boxedcpp.hpp b/boxedcpp/boxedcpp.hpp similarity index 100% rename from dispatch_engine/boxedcpp.hpp rename to boxedcpp/boxedcpp.hpp diff --git a/dispatch_engine/proxy_constructors.hpp b/boxedcpp/proxy_constructors.hpp similarity index 100% rename from dispatch_engine/proxy_constructors.hpp rename to boxedcpp/proxy_constructors.hpp diff --git a/dispatch_engine/proxy_functions.hpp b/boxedcpp/proxy_functions.hpp similarity index 100% rename from dispatch_engine/proxy_functions.hpp rename to boxedcpp/proxy_functions.hpp diff --git a/dispatch_engine/register_function.hpp b/boxedcpp/register_function.hpp similarity index 100% rename from dispatch_engine/register_function.hpp rename to boxedcpp/register_function.hpp diff --git a/dispatch_engine/test.cpp b/boxedcpp/test.cpp similarity index 100% rename from dispatch_engine/test.cpp rename to boxedcpp/test.cpp diff --git a/dispatch_engine/type_info.hpp b/boxedcpp/type_info.hpp similarity index 100% rename from dispatch_engine/type_info.hpp rename to boxedcpp/type_info.hpp diff --git a/dispatch_engine/unittest.cpp b/boxedcpp/unittest.cpp similarity index 100% rename from dispatch_engine/unittest.cpp rename to boxedcpp/unittest.cpp diff --git a/dispatchkit/dispatch_engine/CMakeLists.txt b/dispatchkit/dispatch_engine/CMakeLists.txt new file mode 100644 index 00000000..b6b2c764 --- /dev/null +++ b/dispatchkit/dispatch_engine/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 2.6) +enable_testing() + +project(boxedcpp) + +SET (CMAKE_BUILD_TYPE gdb) +SET (CMAKE_C_FLAGS_GDB " -Wall -ggdb") +SET (CMAKE_CXX_FLAGS_GDB " -Wall -ggdb") + +find_package( Boost 1.36.0 COMPONENTS regex unit_test_framework) +if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + include_directories(.) + + add_executable(boxedcpp_test test.cpp) + + add_executable(boxedcpp_unittest unittest.cpp) + + target_link_libraries(boxedcpp_unittest ${Boost_LIBRARIES}) + +endif() + +add_test(boxedcpp_unittest boxedcpp_unittest) diff --git a/dispatchkit/dispatch_engine/bootstrap.hpp b/dispatchkit/dispatch_engine/bootstrap.hpp new file mode 100644 index 00000000..d0a854a5 --- /dev/null +++ b/dispatchkit/dispatch_engine/bootstrap.hpp @@ -0,0 +1,522 @@ +#ifndef __bootstrap_hpp +#define __bootstrap_hpp__ + +#include "boxedcpp.hpp" +#include "register_function.hpp" + +template +Ret add(P1 p1, P2 p2) +{ + return p1 + p2; +} + +Boxed_Value pod_add(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l + r; +} + + +template +Ret subtract(P1 p1, P2 p2) +{ + return p1 - p2; +} + +Boxed_Value pod_subtract(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l - r; +} + + +template +Ret divide(P1 p1, P2 p2) +{ + return p1 / p2; +} + +Boxed_Value pod_divide(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l / r; +} + + +template +Ret multiply(P1 p1, P2 p2) +{ + return p1 * p2; +} + +Boxed_Value pod_multiply(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l * r; +} + + +template +bool bool_and(P1 p1, P2 p2) +{ + return p1 && p2; +} + +template +bool bool_or(P1 p1, P2 p2) +{ + return p1 || p2; +} + +template +P1 &assign(P1 &p1, const P2 &p2) +{ + return (p1 = p2); +} + +template +P1 &assign_pod(P1 &p1, Boxed_POD_Value v) +{ + if (v.m_isfloat) + { + return (p1 = v.d); + } else { + return (p1 = v.i); + } +} + + +template +bool equals(P1 p1, P2 p2) +{ + return p1 == p2; +} + +bool pod_equals(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l == r; +} + +template +bool not_equals(P1 p1, P2 p2) +{ + return p1 != p2; +} + +bool pod_not_equals(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l != r; +} + + +template +bool less_than(P1 p1, P2 p2) +{ + return p1 < p2; +} + +bool pod_less_than(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l < r; +} + +template +bool greater_than(P1 p1, P2 p2) +{ + return p1 > p2; +} + +bool pod_greater_than(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l > r; +} + +template +bool less_than_equals(P1 p1, P2 p2) +{ + return p1 <= p2; +} + +bool pod_less_than_equals(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l <= r; +} + +template +bool greater_than_equals(P1 p1, P2 p2) +{ + return p1 >= p2; +} + +bool pod_greater_than_equals(Boxed_POD_Value l, Boxed_POD_Value r) +{ + return l >= r; +} + +template +P1 ×equal(P1 &p1, const P2 &p2) +{ + return (p1 *= p2); +} + +template +P1 ×equal_pod(P1 &p1, Boxed_POD_Value r) +{ + if (r.m_isfloat) + { + return (p1 *= r.d); + } else { + return (p1 *= r.i); + } +} + + +template +P1 ÷sequal(P1 &p1, const P2 &p2) +{ + return (p1 /= p2); +} + +template +P1 ÷sequal_pod(P1 &p1, Boxed_POD_Value r) +{ + if (r.m_isfloat) + { + return (p1 /= r.d); + } else { + return (p1 /= r.i); + } +} + + +template +P1 &addsequal(P1 &p1, const P2 &p2) +{ + return (p1 += p2); +} + +template +P1 &addsequal_pod(P1 &p1, Boxed_POD_Value r) +{ + if (r.m_isfloat) + { + return (p1 += r.d); + } else { + return (p1 += r.i); + } +} + +template +P1 &subtractsequal(P1 &p1, const P2 &p2) +{ + return (p1 -= p2); +} + +template +P1 &subtractsequal_pod(P1 &p1, Boxed_POD_Value r) +{ + if (r.m_isfloat) + { + return (p1 -= r.d); + } else { + return (p1 -= r.i); + } +} + +template +P1 &prefixincrement(P1 &p1) +{ + return (++p1); +} + +template +P1 &prefixdecrement(P1 &p1) +{ + return (--p1); +} + +template +P1 &prefixnegate(P1 &p1) +{ + return (p1); +} + +template +P1 &prefixnot(P1 &p1) +{ + return (p1); +} + + +//Add canonical forms of operators +template +void add_oper_equals(Dispatch_Engine &s) +{ + register_function(s, &equals, "="); +} + +template +void add_oper_add(Dispatch_Engine &s) +{ + register_function(s, &add, "+"); +} + +template +void add_oper_add_equals(Dispatch_Engine &s) +{ + register_function(s, &addsequal, "+="); +} + +template +void add_oper_subtract(Dispatch_Engine &s) +{ + register_function(s, &subtract, "-"); +} + +template +void add_oper_divide(Dispatch_Engine &s) +{ + register_function(s, ÷, "-"); +} + +template +void add_oper_multiply(Dispatch_Engine &s) +{ + register_function(s, &multiply, "*"); +} + +template +void add_oper_not_equals(Dispatch_Engine &s) +{ + register_function(s, ¬_equals, "!="); +} + +template +void add_oper_assign_overload(Dispatch_Engine &s) +{ + register_function(s, &assign, "="); +} + + +template +void add_oper_assign(Dispatch_Engine &s) +{ + register_function(s, &assign, "="); +} + + +template +void add_oper_assign_pod(Dispatch_Engine &s) +{ + register_function(s, &assign_pod, "="); +} + + +template +void add_oper_less_than(Dispatch_Engine &s) +{ + register_function(s, &less_than, "<"); +} + +template +void add_oper_greater_than(Dispatch_Engine &s) +{ + register_function(s, &greater_than, ">"); +} + +template +void add_oper_less_than_equals(Dispatch_Engine &s) +{ + register_function(s, &less_than_equals, "<="); +} + +template +void add_oper_greater_than_equals(Dispatch_Engine &s) +{ + register_function(s, &greater_than_equals, ">="); +} + + +template +void add_opers_comparison_overload(Dispatch_Engine &s) +{ + register_function(s, &equals, "=="); + register_function(s, ¬_equals, "!="); + register_function(s, &less_than, "<"); + register_function(s, &greater_than, ">"); + register_function(s, &less_than_equals, "<="); + register_function(s, &greater_than_equals, ">="); +} + +void add_opers_comparison_pod(Dispatch_Engine &s) +{ + register_function(s, &pod_equals, "=="); + register_function(s, &pod_not_equals, "!="); + register_function(s, &pod_less_than, "<"); + register_function(s, &pod_greater_than, ">"); + register_function(s, &pod_less_than_equals, "<="); + register_function(s, &pod_greater_than_equals, ">="); +} + +void add_opers_arithmetic_pod(Dispatch_Engine &s) +{ + register_function(s, &pod_add, "+"); + register_function(s, &pod_subtract, "-"); + register_function(s, &pod_divide, "/"); + register_function(s, &pod_multiply, "*"); +} + +template +void add_opers_comparison(Dispatch_Engine &s) +{ + add_opers_comparison_overload(s); +} + +template +void add_opers_arithmetic_overload(Dispatch_Engine &s) +{ + register_function(s, &add, "+"); + register_function(s, &subtract, "-"); + register_function(s, ÷, "/"); + register_function(s, &multiply, "*"); + register_function(s, ×equal, "*="); + register_function(s, ÷sequal, "/="); + register_function(s, &subtractsequal, "-="); + register_function(s, &addsequal, "+="); + register_function(s, &prefixincrement, "++"); + register_function(s, &prefixdecrement, "--"); + register_function(s, &prefixnegate, "-"); + register_function(s, &prefixnot, "!"); +} + +template +void add_opers_arithmetic_modify_pod(Dispatch_Engine &s) +{ + register_function(s, ×equal_pod, "*="); + register_function(s, ÷sequal_pod, "/="); + register_function(s, &subtractsequal_pod, "-="); + register_function(s, &addsequal_pod, "+="); +} + +template +void add_basic_constructors(Dispatch_Engine &s, const std::string &type) +{ + s.register_function(build_constructor(), type); + s.register_function(build_constructor(), type); + s.register_function(build_constructor(), "clone"); +} + +template +void add_constructor_overload(Dispatch_Engine &s, const std::string &type) +{ + s.register_function(build_constructor(), type); +} + +template +void add_opers_arithmetic(Dispatch_Engine &s) +{ + add_opers_arithmetic_overload(s); + +} + +class bad_boxed_value_cast : public std::bad_cast +{ + public: + bad_boxed_value_cast(const std::string &val) throw() + : m_val(val) + { + } + + virtual ~bad_boxed_value_cast() throw() + { + } + + virtual const char * what() const throw() + { + return m_val.c_str(); + } + + private: + std::string m_val; +}; + +Boxed_Value unknown_assign(Boxed_Value lhs, Boxed_Value rhs) +{ + if (lhs.is_unknown()) + { + return (lhs.assign(rhs)); + } else { + throw bad_boxed_value_cast("boxed_value has a set type alread"); + } +} + +//Built in to_string operator +template +std::string to_string(Input i) +{ + return boost::lexical_cast(i); +} + +template<> std::string to_string(bool b) +{ + if (b) + { + return "true"; + } else { + return "false"; + } +} + +template +void bootstrap_pod_type(Dispatch_Engine &s, const std::string &name) +{ + s.register_type(name); + add_basic_constructors(s, name); + add_oper_assign(s); + add_oper_assign_pod(s); + add_opers_arithmetic(s); + add_opers_arithmetic_modify_pod(s); + register_function(s, &to_string, "to_string"); +} + +void print(const std::string &s) +{ + std::cout << s << std::endl; +} + +void bootstrap(Dispatch_Engine &s) +{ + s.register_type("void"); + + s.register_type("string"); + + add_basic_constructors(s, "bool"); + add_basic_constructors(s, "string"); + add_oper_assign(s); + + register_function(s, &to_string, "to_string"); + register_function(s, &to_string, "to_string"); + register_function(s, &unknown_assign, "="); + + bootstrap_pod_type(s, "double"); + bootstrap_pod_type(s, "int"); + bootstrap_pod_type(s, "size_t"); + bootstrap_pod_type(s, "char"); + bootstrap_pod_type(s, "int64_t"); + + + + add_opers_comparison_pod(s); + add_opers_arithmetic_pod(s); + + add_oper_add(s); + add_oper_add_equals (s); + + register_function(s, &print, "print_string"); + + s.register_function(boost::function(boost::bind(&dump_system, boost::ref(s))), "dump_system"); + s.register_function(boost::function(boost::bind(&dump_object, _1)), "dump_object"); + + + register_function(s, &bool_and, "&&"); + register_function(s, &bool_or, "||"); + +} + +#endif diff --git a/dispatchkit/dispatch_engine/bootstrap_stl.hpp b/dispatchkit/dispatch_engine/bootstrap_stl.hpp new file mode 100644 index 00000000..f5bd0e9f --- /dev/null +++ b/dispatchkit/dispatch_engine/bootstrap_stl.hpp @@ -0,0 +1,82 @@ +#ifndef __bootstrap_stl_hpp +#define __bootstrap_stl_hpp__ + +#include "boxedcpp.hpp" + +template +void bootstrap_reversible_container(Dispatch_Engine &system, const std::string &type) +{ +} + +template +void bootstrap_random_access_container(Dispatch_Engine &system, const std::string &type) +{ + bootstrap_reversible_container(system, type); + + typedef typename ContainerType::reference(ContainerType::*indexoper)(size_t); + + system.register_function( + boost::function(indexoper(&ContainerType::at)), "[]"); + system.register_function( + boost::function(indexoper(&ContainerType::operator[])), "at"); +} + +template +void bootstrap_assignable(Dispatch_Engine &system, const std::string &type) +{ + system.register_function( + boost::function(&Assignable::operator=), "="); +} + +template +void bootstrap_container(Dispatch_Engine &system, const std::string &type) +{ + bootstrap_assignable(system, type); + + system.register_function( + boost::function(&ContainerType::size), "size"); + system.register_function( + boost::function(&ContainerType::size), "maxsize"); +} + +template +void bootstrap_forward_container(Dispatch_Engine &system, const std::string &type) +{ + bootstrap_container(system, type); +} + +template +void bootstrap_default_constructible(Dispatch_Engine &system, const std::string &type) +{ + system.register_function(build_constructor(), type); +} + +template +void bootstrap_sequence(Dispatch_Engine &system, const std::string &type) +{ + bootstrap_forward_container(system, type); + bootstrap_default_constructible(system, type); +} + +template +void bootstrap_back_insertion_sequence(Dispatch_Engine &system, const std::string &type) +{ + bootstrap_sequence(system, type); + + + typedef typename SequenceType::reference (SequenceType::*backptr)(); + + system.register_function(boost::function(backptr(&SequenceType::back)), "back"); + system.register_function(boost::function(&SequenceType::push_back), "push_back"); + system.register_function(boost::function(&SequenceType::pop_back), "pop_back"); +} + +template +void bootstrap_vector(Dispatch_Engine &system, const std::string &type) +{ + system.register_type(type); + bootstrap_random_access_container(system, type); + bootstrap_back_insertion_sequence(system, type); +} + +#endif diff --git a/dispatchkit/dispatch_engine/boxed_value.hpp b/dispatchkit/dispatch_engine/boxed_value.hpp new file mode 100644 index 00000000..a15f0939 --- /dev/null +++ b/dispatchkit/dispatch_engine/boxed_value.hpp @@ -0,0 +1,385 @@ +#ifndef __boxed_value_hpp__ +#define __boxed_value_hpp__ + +#include "type_info.hpp" +#include +#include + +#include + +class Boxed_Value +{ + private: + struct Data + { + Data(const Type_Info &ti, + const boost::any &to, + bool tr) + : m_type_info(ti), m_obj(to), m_is_ref(tr) + { + } + + Data &operator=(const Data &rhs) + { + m_type_info = rhs.m_type_info; + m_obj = rhs.m_obj; + m_is_ref = rhs.m_is_ref; + + return *this; + } + + Type_Info m_type_info; + boost::any m_obj; + bool m_is_ref; + }; + + public: + struct Void_Type + { + }; + + template + explicit Boxed_Value(boost::shared_ptr obj) + : m_data(new Data( + Get_Type_Info()(), + boost::any(obj), + false) + ) + { + } + + template + explicit Boxed_Value(boost::reference_wrapper obj) + : m_data(new Data( + Get_Type_Info()(), + boost::any(obj), + true) + ) + { + } + + template + explicit Boxed_Value(const T& t) + : m_data(new Data( + Get_Type_Info()(), + boost::any(boost::shared_ptr(new T(t))), + false) + ) + { + } + + Boxed_Value(Boxed_Value::Void_Type) + : m_data(new Data( + Get_Type_Info()(), + boost::any(), + false) + ) + { + } + + Boxed_Value(const Boxed_Value &t_so) + : m_data(t_so.m_data) + { + } + + Boxed_Value() + : m_data(new Data( + Type_Info(), + boost::any(), + false) + ) + { + } + + Boxed_Value assign(const Boxed_Value &rhs) + { + (*m_data) = (*rhs.m_data); + return *this; + } + + Boxed_Value &operator=(const Boxed_Value &rhs) + { + m_data = rhs.m_data; + /* + std::cout << "operator= called" << std::endl; + m_data->m_obj = rhs.m_data->m_obj; + m_data->m_type_info = rhs.m_data->m_type_info; + m_data->m_is_ref = rhs.m_data->m_is_ref; + (*m_data) = (*rhs.m_data); + */ + return *this; + } + + const Type_Info &get_type_info() const + { + return m_data->m_type_info; + } + + bool is_unknown() const + { + return m_data->m_type_info.m_is_unknown; + } + + boost::any get() const + { + return m_data->m_obj; + } + + bool is_ref() const + { + return m_data->m_is_ref; + } + + private: + boost::shared_ptr m_data; +}; + + +//cast_help specializations +template +struct Cast_Helper +{ + typename boost::reference_wrapper::type > operator()(Boxed_Value ob) + { + if (ob.is_ref()) + { + return boost::cref((boost::any_cast >(ob.get())).get()); + } else { + return boost::cref(*(boost::any_cast >(ob.get()))); + } + } +}; + +template +struct Cast_Helper +{ + typename boost::reference_wrapper::type > operator()(Boxed_Value ob) + { + if (ob.is_ref()) + { + return boost::cref((boost::any_cast >(ob.get())).get()); + } else { + return boost::cref(*(boost::any_cast >(ob.get()))); + } + } +}; + +template +struct Cast_Helper +{ + const Result *operator()(Boxed_Value ob) + { + if (ob.is_ref()) + { + return (boost::any_cast >(ob.get())).get_pointer(); + } else { + return (boost::any_cast >(ob.get())).get(); + } + } +}; + +template +struct Cast_Helper +{ + Result *operator()(Boxed_Value ob) + { + if (ob.is_ref()) + { + return (boost::any_cast >(ob.get())).get_pointer(); + } else { + return (boost::any_cast >(ob.get())).get(); + } + } +}; + +template +struct Cast_Helper +{ + typename boost::reference_wrapper operator()(Boxed_Value ob) + { + if (ob.is_ref()) + { + return boost::any_cast >(ob.get()); + } else { + return boost::ref(*(boost::any_cast >(ob.get()))); + } + } +}; + +template +struct Cast_Helper > +{ + typename boost::shared_ptr operator()(Boxed_Value ob) + { + return boost::any_cast >(ob.get()); + } +}; + + +template<> +struct Cast_Helper +{ + Boxed_Value operator()(Boxed_Value ob) + { + return ob; + } +}; + + +struct Boxed_POD_Value +{ + Boxed_POD_Value(const Boxed_Value &v) + : d(0), i(0), m_isfloat(false) + { + const int inp_ = int(v.get_type_info().m_type_info); + + const int char_ = int(&typeid(char)); + const int bool_ = int(&typeid(bool)); + + const int double_ = int(&typeid(double)); + const int float_ = int(&typeid(float)); + + const int long_ = int(&typeid(long)); + const int unsigned_long_ = int(&typeid(unsigned long)); + const int int_ = int(&typeid(int)); + const int unsigned_int_ = int(&typeid(unsigned int)); + + const int uint8_t_ = int(&typeid(uint8_t)); + const int uint16_t_ = int(&typeid(uint16_t)); + const int uint32_t_ = int(&typeid(uint32_t)); +// const int uint64_t_ = int(&typeid(uint64_t)); + + const int int8_t_ = int(&typeid(int8_t)); + const int int16_t_ = int(&typeid(int16_t)); + const int int32_t_ = int(&typeid(int32_t)); + const int int64_t_ = int(&typeid(int64_t)); + + if (inp_ == double_) + { + d = Cast_Helper()(v); + m_isfloat = true; + } else if (inp_ == float_) { + d = Cast_Helper()(v); + m_isfloat = true; + } else if (inp_ == bool_ ) { + i = Cast_Helper()(v); + } else if (inp_ == char_) { + i = Cast_Helper()(v); + } else if (inp_ == int_) { + i = Cast_Helper()(v); + } else if (inp_ == unsigned_int_) { + i = Cast_Helper()(v); + } else if (inp_ == long_) { + i = Cast_Helper()(v); + } else if (inp_ == unsigned_long_) { + i = Cast_Helper()(v); + } else if (inp_ == int8_t_) { + i = Cast_Helper()(v); + } else if (inp_ == int16_t_) { + i = Cast_Helper()(v); + } else if (inp_ == int32_t_) { + i = Cast_Helper()(v); + } else if (inp_ == int64_t_) { + i = Cast_Helper()(v); + } else if (inp_ == uint8_t_) { + i = Cast_Helper()(v); + } else if (inp_ == uint16_t_) { + i = Cast_Helper()(v); + } else if (inp_ == uint32_t_) { + i = Cast_Helper()(v); + } else { + throw boost::bad_any_cast(); + } + } + + + bool operator==(const Boxed_POD_Value &r) const + { + return ((m_isfloat)?d:i) == ((r.m_isfloat)?r.d:r.i); + } + + bool operator<(const Boxed_POD_Value &r) const + { + return ((m_isfloat)?d:i) < ((r.m_isfloat)?r.d:r.i); + } + + bool operator>(const Boxed_POD_Value &r) const + { + return ((m_isfloat)?d:i) > ((r.m_isfloat)?r.d:r.i); + } + + bool operator>=(const Boxed_POD_Value &r) const + { + return ((m_isfloat)?d:i) >= ((r.m_isfloat)?r.d:r.i); + } + + bool operator<=(const Boxed_POD_Value &r) const + { + return ((m_isfloat)?d:i) <= ((r.m_isfloat)?r.d:r.i); + } + + bool operator!=(const Boxed_POD_Value &r) const + { + return ((m_isfloat)?d:i) != ((r.m_isfloat)?r.d:r.i); + } + + Boxed_Value operator+(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i + r.i); + } + + return Boxed_Value(((m_isfloat)?d:i) + ((r.m_isfloat)?r.d:r.i)); + } + + Boxed_Value operator*(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i * r.i); + } + + return Boxed_Value(((m_isfloat)?d:i) * ((r.m_isfloat)?r.d:r.i)); + } + + Boxed_Value operator/(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i / r.i); + } + + return Boxed_Value(((m_isfloat)?d:i) / ((r.m_isfloat)?r.d:r.i)); + } + + Boxed_Value operator-(const Boxed_POD_Value &r) const + { + if (!m_isfloat && !r.m_isfloat) + { + return Boxed_Value(i - r.i); + } + + return Boxed_Value(((m_isfloat)?d:i) - ((r.m_isfloat)?r.d:r.i)); + } + + double d; + int64_t i; + + bool m_isfloat; +}; + +template<> +struct Cast_Helper +{ + Boxed_POD_Value operator()(Boxed_Value ob) + { + return Boxed_POD_Value(ob); + } +}; + + + + +#endif + diff --git a/dispatchkit/dispatch_engine/boxedcpp.hpp b/dispatchkit/dispatch_engine/boxedcpp.hpp new file mode 100644 index 00000000..2ea25e5a --- /dev/null +++ b/dispatchkit/dispatch_engine/boxedcpp.hpp @@ -0,0 +1,209 @@ +#ifndef __boxedcpp_system_hpp__ +#define __boxedcpp_system_hpp__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "boxed_value.hpp" +#include "type_info.hpp" +#include "proxy_functions.hpp" +#include "proxy_constructors.hpp" + +class Dispatch_Engine +{ + public: + typedef std::multimap > Function_Map; + typedef std::map Type_Name_Map; + typedef std::map Scope; + typedef std::deque Stack; + + Dispatch_Engine() + { + m_scopes.push_back(Scope()); + } + + void register_function(const boost::shared_ptr &f, const std::string &name) + { + m_functions.insert(std::make_pair(name, f)); + } + + + template + void register_function(const Function &func, const std::string &name) + { + m_functions.insert(std::make_pair(name, boost::shared_ptr(new Proxy_Function_Impl(func)))); + } + + + template + void set_object(const std::string &name, const Class &obj) + { + for (int i = m_scopes.size()-1; i >= 0; --i) + { + std::map::const_iterator itr = m_scopes[i].find(name); + if (itr != m_scopes[i].end()) + { + m_scopes[i][name] = Boxed_Value(obj); + return; + } + } + + add_object(name, obj); + } + + template + void add_object(const std::string &name, const Class &obj) + { + m_scopes.back()[name] = Boxed_Value(obj); + } + + void new_scope() + { + m_scopes.push_back(Scope()); + } + + void pop_scope() + { + if (m_scopes.size() > 1) + { + m_scopes.pop_back(); + } else { + throw std::range_error("Unable to pop global stack"); + } + } + + Stack get_stack() + { + return m_scopes; + } + + Stack set_stack(Stack s) + { + swap(s, m_scopes); + return s; + } + + + Boxed_Value get_object(const std::string &name) const + { + for (int i = m_scopes.size()-1; i >= 0; --i) + { + std::map::const_iterator itr = m_scopes[i].find(name); + if (itr != m_scopes[i].end()) + { + return itr->second; + } + } + + throw std::range_error("Object not known: " + name); + } + + template + void register_type(const std::string &name) + { + m_types.insert(std::make_pair(name, Get_Type_Info()())); + } + + std::vector get_types() const + { + return std::vector(m_types.begin(), m_types.end()); + } + + std::vector > + get_function(const std::string &t_name) const + { + std::vector > funcs; + + try { + funcs.insert(funcs.end(), + Function_Map::value_type( + t_name, + Cast_Helper()(get_object(t_name))) + ); + } catch (const std::bad_cast &) { + } catch (const std::range_error &) { + } + + std::pair range + = m_functions.equal_range(t_name); + + funcs.insert(funcs.end(), range.first, range.second); + return funcs; + } + + std::vector get_functions() const + { + return std::vector(m_functions.begin(), m_functions.end()); + } + + private: + std::deque m_scopes; + + Function_Map m_functions; + Type_Name_Map m_types; +}; + +void dump_object(Boxed_Value o) +{ + std::cout << o.get_type_info().m_type_info->name() << std::endl; +} + +void dump_type(const Type_Info &type) +{ + std::cout << type.m_bare_type_info->name(); +} + +void dump_function(const Dispatch_Engine::Function_Map::value_type &f) +{ + std::vector params = f.second->get_param_types(); + + dump_type(params.front()); + std::cout << " " << f.first << "("; + + for (std::vector::const_iterator itr = params.begin() + 1; + itr != params.end(); + ++itr) + { + dump_type(*itr); + std::cout << ", "; + } + + std::cout << ")" << std::endl; +} + +void dump_system(const Dispatch_Engine &s) +{ + std::cout << "Registered Types: " << std::endl; + std::vector types = s.get_types(); + for (std::vector::const_iterator itr = types.begin(); + itr != types.end(); + ++itr) + { + std::cout << itr->first << ": "; + dump_type(itr->second); + std::cout << std::endl; + } + + + std::cout << std::endl; std::vector funcs = s.get_functions(); + + std::cout << "Functions: " << std::endl; + for (std::vector::const_iterator itr = funcs.begin(); + itr != funcs.end(); + ++itr) + { + dump_function(*itr); + } + std::cout << std::endl; +} + + + +#endif diff --git a/dispatchkit/dispatch_engine/proxy_constructors.hpp b/dispatchkit/dispatch_engine/proxy_constructors.hpp new file mode 100644 index 00000000..cbb2b3ec --- /dev/null +++ b/dispatchkit/dispatch_engine/proxy_constructors.hpp @@ -0,0 +1,46 @@ +#include + +#ifndef BOOST_PP_IS_ITERATING +#ifndef __proxy_constructors_hpp__ +#define __proxy_constructors_hpp__ + +#include +#include +#include + +template +boost::shared_ptr constructor() +{ + return boost::shared_ptr(new Class()); +} + +template +boost::function ()> build_constructor() +{ + typedef boost::shared_ptr (*func)(); + return boost::function ()>(func(&(constructor))); +} + +#define BOOST_PP_ITERATION_LIMITS ( 1, 10 ) +#define BOOST_PP_FILENAME_1 "proxy_constructors.hpp" +#include BOOST_PP_ITERATE() +# endif +#else +# define n BOOST_PP_ITERATION() + + +template +boost::shared_ptr constructor( BOOST_PP_ENUM_BINARY_PARAMS(n, Param, p) ) +{ + return boost::shared_ptr(new Class( BOOST_PP_ENUM_PARAMS(n, p) )); +} + +template +boost::function (BOOST_PP_ENUM_PARAMS(n, Param))> build_constructor() +{ + typedef boost::shared_ptr (*func)(BOOST_PP_ENUM_PARAMS(n, Param)); + return boost::function (BOOST_PP_ENUM_PARAMS(n, Param))>(func(&(constructor))); +} + +#endif + diff --git a/dispatchkit/dispatch_engine/proxy_functions.hpp b/dispatchkit/dispatch_engine/proxy_functions.hpp new file mode 100644 index 00000000..0645a5d1 --- /dev/null +++ b/dispatchkit/dispatch_engine/proxy_functions.hpp @@ -0,0 +1,228 @@ +#include + +#define gettypeinfo(z,n,text) ti.push_back(Get_Type_Info()()); +#define casthelper(z,n,text) ,Cast_Helper()(params[n]) + + +#ifndef BOOST_PP_IS_ITERATING +#ifndef __proxy_functions_hpp__ +#define __proxy_functions_hpp__ + +#include "boxed_value.hpp" +#include "type_info.hpp" +#include +#include +#include +#include +#include + +// handle_return implementations +template +struct Handle_Return +{ + Boxed_Value operator()(const boost::function &f) + { + return Boxed_Value(f()); + } +}; + +template +struct Handle_Return +{ + Boxed_Value operator()(const boost::function &f) + { + return Boxed_Value(boost::ref(f())); + } +}; + +template<> +struct Handle_Return +{ + Boxed_Value operator()(const boost::function &f) + { + return f(); + } +}; + +template<> +struct Handle_Return +{ + Boxed_Value operator()(const boost::function &f) + { + return f(); + } +}; + +template<> +struct Handle_Return +{ + Boxed_Value operator()(const boost::function &f) + { + f(); + return Boxed_Value(Boxed_Value::Void_Type()); + } +}; + + +// Build param type list (variadic) +template +std::vector build_param_type_list(const boost::function &f) +{ + std::vector ti; + ti.push_back(Get_Type_Info()()); + return ti; +} + +// call_func implementations (variadic) +template +Boxed_Value call_func(const boost::function &f, const std::vector ¶ms) +{ + if (params.size() != 0) + { + throw std::range_error("Incorrect number of parameters"); + } else { + return Handle_Return()(f); + } +} + +struct Param_List_Builder +{ + Param_List_Builder &operator<<(const Boxed_Value &so) + { + objects.push_back(so); + return *this; + } + + template + Param_List_Builder &operator<<(T t) + { + objects.push_back(Boxed_Value(t)); + return *this; + } + + operator const std::vector &() const + { + return objects; + } + + std::vector objects; +}; + + +#define BOOST_PP_ITERATION_LIMITS ( 1, 10 ) +#define BOOST_PP_FILENAME_1 "proxy_functions.hpp" +#include BOOST_PP_ITERATE() + +class Proxy_Function +{ + public: + virtual ~Proxy_Function() {} + virtual Boxed_Value operator()(const std::vector ¶ms) = 0; + virtual std::vector get_param_types() = 0; + +}; + +class Dynamic_Proxy_Function : public Proxy_Function +{ + public: + Dynamic_Proxy_Function(const boost::function &)> &t_f, int arity=-1) + : m_f(t_f), m_arity(arity) + { + } + + virtual ~Dynamic_Proxy_Function() {} + + virtual Boxed_Value operator()(const std::vector ¶ms) + { + if (m_arity < 0 || params.size() == size_t(m_arity)) + { + return m_f(params); + } else { + throw std::range_error("Incorrect number of parameters"); + } + } + + virtual std::vector get_param_types() + { + return build_param_type_list(m_f); + } + + private: + boost::function &)> m_f; + int m_arity; +}; + +template +class Proxy_Function_Impl : public Proxy_Function +{ + public: + Proxy_Function_Impl(const Func &f) + : m_f(f) + { + } + + virtual ~Proxy_Function_Impl() {} + + + virtual Boxed_Value operator()(const std::vector ¶ms) + { + return call_func(m_f, params); + } + + virtual std::vector get_param_types() + { + return build_param_type_list(m_f); + } + + private: + Func m_f; +}; + +Boxed_Value dispatch(const std::vector > > &funcs, + const std::vector &plist) +{ + for (std::vector > >::const_iterator itr = funcs.begin(); + itr != funcs.end(); + ++itr) + { + try { + return (*itr->second)(plist); + } catch (const std::bad_cast &) { + //try again + } catch (const std::range_error &) { + //invalid num params, try again + } + } + + throw std::runtime_error("No matching function to dispatch to"); +} + +# endif +#else +# define n BOOST_PP_ITERATION() + +template +std::vector build_param_type_list(const boost::function &f) +{ + std::vector ti; + ti.push_back(Get_Type_Info()()); + + BOOST_PP_REPEAT(n, gettypeinfo, ~) + + return ti; +} + +template +Boxed_Value call_func(const boost::function &f, + const std::vector ¶ms) +{ + if (params.size() != n) + { + throw std::range_error("Incorrect number of parameters"); + } else { + return Handle_Return()(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~))); + } +} + +#endif + diff --git a/dispatchkit/dispatch_engine/register_function.hpp b/dispatchkit/dispatch_engine/register_function.hpp new file mode 100644 index 00000000..1362f82c --- /dev/null +++ b/dispatchkit/dispatch_engine/register_function.hpp @@ -0,0 +1,35 @@ +#include + +#ifndef BOOST_PP_IS_ITERATING +#ifndef __register_function_hpp__ +#define __register_function_hpp__ + +#include +#include +#include + + +#define BOOST_PP_ITERATION_LIMITS ( 0, 10 ) +#define BOOST_PP_FILENAME_1 "register_function.hpp" + +#include BOOST_PP_ITERATE() + +# endif +#else +# define n BOOST_PP_ITERATION() + +template +void register_function(Dispatch_Engine &s, Ret (*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name) +{ + s.register_function(boost::function(f), name); +} + +template +void register_function(Dispatch_Engine &s, Ret (Class::*f)(BOOST_PP_ENUM_PARAMS(n, Param)), const std::string &name) +{ + s.register_function(boost::function(f), name); +} + + +#endif + diff --git a/dispatchkit/dispatch_engine/test.cpp b/dispatchkit/dispatch_engine/test.cpp new file mode 100644 index 00000000..5e15d38e --- /dev/null +++ b/dispatchkit/dispatch_engine/test.cpp @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include + +#include "boxedcpp.hpp" +#include "bootstrap.hpp" +#include "bootstrap_stl.hpp" + +struct Test +{ + Test(const std::string &s) + : message(s) + { + std::cout << "Test class constructed with value: " << s << std::endl; + } + + void show_message() + { + std::cout << "Constructed Message: " << message << std::endl; + } + + std::string &get_message() + { + return message; + } + + std::string message; +}; + + + +Boxed_Value named_func_call(Dispatch_Engine &ss, + const std::string &nametocall, const std::vector ¶ms) +{ + if (params.size() == 2) + { + return dispatch(ss.get_function(nametocall), params); + } else { + throw std::runtime_error("Invalid num params"); + } +} + +// A function that takes a dynamic list of params +// and calls a bunch of conversion functions on them and +// returns the result as a boxed_value +Boxed_Value dynamic_function(Dispatch_Engine &ss, const std::string &name, + const std::vector ¶ms) +{ + if (name == "concat_string") + { + Boxed_Value result; + + //Return a void if there is nothing in the array + if (params.size() == 0) + { + return result; + } else { + //else, prepopulate the result with a string conversion of the first + //param + result = + dispatch(ss.get_function("to_string"), Param_List_Builder() << params[0]); + } + + //Then, loop over all remaining params, converting them to strings and adding + //them to the result. This example maybe bette served with a string += operator + //implementation, but it works. + for (size_t i = 1; i < params.size(); ++i) + { + result = + dispatch(ss.get_function("+"), Param_List_Builder() << result << + dispatch(ss.get_function("to_string"), Param_List_Builder() << params[i])); + } + + return result; + } else { + throw std::runtime_error("Unknown function call"); + } +} + +void test(const std::string &p) +{ + std::cout << "Test: " << p << std::endl; +} + +//Test main +int main() +{ + Dispatch_Engine ss; + bootstrap(ss); + bootstrap_vector >(ss, "VectorInt"); + dump_system(ss); + + //Calling a function by name and allowing the built in dispatch mechanism to + //choose the most appropriate version of the function + Boxed_Value addresult = dispatch(ss.get_function("+"), Param_List_Builder() << double(5.1) << double(10.3)); + + //Using the Cast_Helper to unbox the resultant value and output it + std::cout << Cast_Helper()(addresult) << std::endl; + + //Using the Boxed_Value as input to another function, again with automatic dispatch. + //This time we will not bother saving the result and will instead send it straight out + std::cout << Cast_Helper()( + dispatch(ss.get_function("*"), Param_List_Builder() << 2 << addresult) + ) << std::endl; + + //Register a new function, this one with typing for us, so we don't have to ubox anything + //right here + + //Now we have a print method, let's try to print out the earlier example: + //so, we dispatch the to_string and pass its result as a param to "print" + //In this example we don't bother with temporaries and we don't have to know + //anything about types + dispatch(ss.get_function("print"), + Param_List_Builder() << dispatch(ss.get_function("to_string"), Param_List_Builder() << addresult)); + + // Now we are going to register a new dynamic function, + // when this function is called the objects are not unboxed, but passed + // in in their boxed state + ss.register_function(boost::shared_ptr(new Dynamic_Proxy_Function(boost::bind(&dynamic_function, boost::ref(ss), "concat_string", _1))), "concat_string"); + + + // Call our newly defined dynamic function with 10 parameters, then send + // its output to the "print" function + dispatch(ss.get_function("print"), + Param_List_Builder() << dispatch(ss.get_function("concat_string"), + Param_List_Builder() << std::string("\n\t") << std::string("The Value Was: ") + << double(42.5) << std::string(".") + << '\n' + << '\t' << std::string("The old value was: ") + << addresult << '.' << '\n' )); + + + + + //Register some local methods of the "Test" class + ss.register_function(build_constructor(), "Test"); + + register_function(ss, &Test::get_message, "get_message"); + register_function(ss, &Test::show_message, "show_message"); + + + //Create a new object using the "Test" constructor, passing the param "Yo". + //Then, add the new object to the system with the name "testobj2" + ss.add_object("testobj2", + dispatch(ss.get_function("Test"), Param_List_Builder() << std::string("Yo"))); + + // Look up and store a reference to our new object + std::vector sos; + sos.push_back(ss.get_object("testobj2")); + + //Print the message the object was created with + dispatch(ss.get_function("show_message"), sos); + + //Now, get a reference to the object's stored message + Boxed_Value stringref = dispatch(ss.get_function("get_message"), sos); + + //Unbox it using Cast_Helper + std::string &sr = Cast_Helper()(stringref); + + //Update the value of the reference + sr = "Bob Updated The message"; + + //Now, prove that the reference was successfully acquired + //and we are able to peek into the boxed types + dispatch(ss.get_function("show_message"), sos); + + + // Finally, we are going to register some named function aliases, for + // the fun of it + ss.register_function(boost::shared_ptr( + new Dynamic_Proxy_Function(boost::bind(&named_func_call, boost::ref(ss), "+", _1))), "add"); + + //Call our newly named "add" function (which in turn dispatches +) + + std::cout << "Result of add function: " << + Cast_Helper()(dispatch(ss.get_function("add"), Param_List_Builder() << 5 << 2)) + << std::endl; + + + ss.set_object("myfunc", boost::shared_ptr(new Proxy_Function_Impl >(&test))); + + dispatch(ss.get_function("myfunc"), Param_List_Builder() << std::string("hello function variable")); + +} + diff --git a/dispatchkit/dispatch_engine/type_info.hpp b/dispatchkit/dispatch_engine/type_info.hpp new file mode 100644 index 00000000..5d2db8d9 --- /dev/null +++ b/dispatchkit/dispatch_engine/type_info.hpp @@ -0,0 +1,80 @@ +#ifndef __type_info_hpp__ +#define __type_info_hpp__ + +#include +#include +struct Type_Info +{ + Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void, + const std::type_info *t_ti, const std::type_info *t_bareti) + : m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer), + m_type_info(t_ti), m_bare_type_info(t_bareti), + m_is_unknown(false) + { + } + + Type_Info() + : m_is_const(false), m_is_reference(false), m_is_pointer(false), + m_is_void(false), m_type_info(0), m_bare_type_info(0), + m_is_unknown(true) + { + } + + Type_Info &operator=(const Type_Info &ti) + { + m_is_const = ti.m_is_const; + m_is_reference = ti.m_is_reference; + m_is_pointer = ti.m_is_pointer; + m_is_void = ti.m_is_void; + m_type_info = ti.m_type_info; + m_bare_type_info = ti.m_bare_type_info; + m_is_unknown = ti.m_is_unknown; + return *this; + } + + bool m_is_const; + bool m_is_reference; + bool m_is_pointer; + bool m_is_void; + const std::type_info *m_type_info; + const std::type_info *m_bare_type_info; + bool m_is_unknown; + }; + +template +struct Get_Type_Info +{ + Type_Info operator()() + { + return Type_Info(boost::is_const::value, boost::is_reference::value, boost::is_pointer::value, + boost::is_void::value, + &typeid(T), + &typeid(typename boost::remove_const::type>::type>::type)); + } +}; + +template +struct Get_Type_Info > +{ + Type_Info operator()() + { + return Type_Info(boost::is_const::value, boost::is_reference::value, boost::is_pointer::value, + boost::is_void::value, + &typeid(boost::shared_ptr ), + &typeid(typename boost::remove_const::type>::type>::type)); + } +}; + +template +struct Get_Type_Info > +{ + Type_Info operator()() + { + return Type_Info(boost::is_const::value, boost::is_reference::value, boost::is_pointer::value, + boost::is_void::value, + &typeid(boost::reference_wrapper ), + &typeid(typename boost::remove_const::type>::type>::type)); + } +}; + +#endif diff --git a/dispatchkit/dispatch_engine/unittest.cpp b/dispatchkit/dispatch_engine/unittest.cpp new file mode 100644 index 00000000..1062a2a8 --- /dev/null +++ b/dispatchkit/dispatch_engine/unittest.cpp @@ -0,0 +1,17 @@ +#include "boxedcpp.hpp" +#include "bootstrap.hpp" + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE boxedcpp_unittests +#include + +BOOST_AUTO_TEST_CASE( add_operators ) +{ + Dispatch_Engine ss; + bootstrap(ss); + dump_system(ss); + + BOOST_CHECK_EQUAL(Cast_Helper()(dispatch(ss.get_function("+"), Param_List_Builder() << double(5.1) << double(10.3))), 15.4); + + +}