Compare commits

...

2 Commits

Author SHA1 Message Date
Jason Turner
fc0264272f More thorough support for unique_ptr
* has a few issues, the main problem is that the base_class conversion
   is found before the unique_ptr conversion, so converting fails
2017-02-22 12:26:50 -08:00
Jason Turner
f431dbffb4 Update catch.hpp 2017-02-22 12:26:42 -08:00
6 changed files with 1130 additions and 491 deletions

View File

@ -86,6 +86,12 @@ namespace chaiscript
// either way, we are not responsible if it doesn't work
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_conversion<Type>(t_conversions->saves(), bv), t_conversions));
} catch (...) {
try {
throw;
} catch (const std::exception &e) {
std::cout << "EXCEPTION: " << e.what() << std::endl;
}
try {
// try going the other way
return(detail::Cast_Helper<Type>::cast((*t_conversions)->boxed_type_down_conversion<Type>(t_conversions->saves(), bv), t_conversions));

View File

@ -238,6 +238,11 @@ namespace chaiscript
return m_data->m_type_info.bare_equal(ti);
}
void reset_pointers() const
{
m_data->m_data_ptr = nullptr;
m_data->m_const_data_ptr = nullptr;
}
template<typename T>
auto pointer_sentinel(std::shared_ptr<T> &ptr) const

View File

@ -367,6 +367,7 @@ namespace chaiscript
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
/// \todo error if a conversion already exists
m_conversions.insert(conversion);
std::cout << "Adding Conversion: TO: " << conversion->to().bare_type_info()->name() << " FROM: " << conversion->from().bare_type_info()->name() << std::endl;
m_convertableTypes.insert({conversion->to().bare_type_info(), conversion->from().bare_type_info()});
m_num_types = m_convertableTypes.size();
}
@ -410,12 +411,17 @@ namespace chaiscript
Boxed_Value boxed_type_conversion(const Type_Info &to, Conversion_Saves &t_saves, const Boxed_Value &from) const
{
try {
Boxed_Value ret = get_conversion(to, from.get_type_info())->convert(from);
std::cout << "boxed_type_conversion" << std::endl;
auto conversion = get_conversion(to, from.get_type_info());
std::cout << "Conversion found!" << std::endl;
Boxed_Value ret = conversion->convert(from);
std::cout << "Conversion succeeded!" << std::endl;
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
return ret;
} catch (const std::out_of_range &) {
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "No known conversion");
} catch (const std::bad_cast &) {
std::cout << "Bad Cast!?" << std::endl;
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "Unable to perform dynamic_cast operation");
}
}
@ -423,6 +429,7 @@ namespace chaiscript
Boxed_Value boxed_type_down_conversion(const Type_Info &from, Conversion_Saves &t_saves, const Boxed_Value &to) const
{
try {
std::cout << "boxed_type_down_conversion" << std::endl;
Boxed_Value ret = get_conversion(to.get_type_info(), from)->convert_down(to);
if (t_saves.enabled) { t_saves.saves.push_back(ret); }
return ret;
@ -455,10 +462,12 @@ namespace chaiscript
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
std::cout << "Getting conversion TO: " << to.name() << " FROM: " << from.name() << std::endl;
const auto itr = find(to, from);
if (itr != m_conversions.end())
{
std::cout << "Found" << std::endl;
return *itr;
} else {
throw std::out_of_range("No such conversion exists from " + from.bare_name() + " to " + to.bare_name());
@ -476,7 +485,7 @@ namespace chaiscript
return std::find_if(m_conversions.begin(), m_conversions.end(),
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion) -> bool
{
return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from))
return (conversion->to().type_info == to.type_info conversion->to().bare_equal(to) && conversion->from().bare_equal(from))
|| (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from));
}
);
@ -485,6 +494,7 @@ namespace chaiscript
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find(
const Type_Info &to, const Type_Info &from) const
{
std::cout << "Finding: TO: " << to.bare_type_info()->name() << " FROM: " << from.bare_type_info()->name() << std::endl;
return std::find_if(m_conversions.begin(), m_conversions.end(),
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
{
@ -588,6 +598,24 @@ namespace chaiscript
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<Callable>>(t_from, t_to, t_func);
}
template<typename From, typename To>
Type_Conversion unique_ptr_conversion()
{
static_assert(std::is_convertible<From, To>::value, "Types are not automatically convertible");
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
std::cout << " unique_ptr_conversion " << std::endl;
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
auto bv = chaiscript::Boxed_Value(std::unique_ptr<To>(detail::Cast_Helper<std::unique_ptr<From> &&>::cast(t_bv, nullptr)));
t_bv.reset_pointers();
return bv;
};
return chaiscript::make_shared<detail::Type_Conversion_Base,
detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::unique_ptr<From>>(),
user_type<std::unique_ptr<To>>(), func);
}
template<typename From, typename To, typename Callable>
Type_Conversion type_conversion(const Callable &t_function)
{

View File

@ -143,11 +143,11 @@ namespace chaiscript
}
};
// shared_ptr
template<typename T>
struct Get_Type_Info<std::shared_ptr<T> >
{
// typedef T type;
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
@ -176,6 +176,45 @@ namespace chaiscript
}
};
// unique_ptr
template<typename T>
struct Get_Type_Info<std::unique_ptr<T> >
{
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
&typeid(std::unique_ptr<T> ),
&typeid(typename Bare_Type<T>::type));
}
};
template<typename T>
struct Get_Type_Info<std::unique_ptr<T> &> : Get_Type_Info<std::unique_ptr<T>>
{
};
template<typename T>
struct Get_Type_Info<std::unique_ptr<T> &&> : Get_Type_Info<std::unique_ptr<T>>
{
};
template<typename T>
struct Get_Type_Info<const std::unique_ptr<T> &>
{
static constexpr Type_Info get()
{
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
std::is_void<T>::value,
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<typename std::remove_reference<T>::type>::type, bool>::value,
&typeid(const std::unique_ptr<T> &),
&typeid(typename Bare_Type<T>::type));
}
};
// reference_wrapper
template<typename T>
struct Get_Type_Info<std::reference_wrapper<T> >
{

File diff suppressed because it is too large Load Diff

View File

@ -1154,6 +1154,8 @@ std::unique_ptr<Unique_Ptr_Test_Class> make_Unique_Ptr_Test_Class()
return std::make_unique<Unique_Ptr_Test_Class>();
}
TEST_CASE("Call methods through unique_ptr")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
@ -1180,6 +1182,10 @@ std::unique_ptr<Unique_Ptr_Test_Derived_Class> make_Unique_Ptr_Test_Derived_Clas
return std::make_unique<Unique_Ptr_Test_Derived_Class>();
}
void call_unique_ptr_with_conversion_to_base(std::unique_ptr<Unique_Ptr_Test_Base_Class> &&)
{
}
TEST_CASE("Call methods on base class through unique_ptr<derived>")
{
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
@ -1190,6 +1196,16 @@ TEST_CASE("Call methods on base class through unique_ptr<derived>")
chai.add(chaiscript::base_class<Unique_Ptr_Test_Base_Class, Unique_Ptr_Test_Derived_Class>());
CHECK(chai.eval<int>("uptr.getI()") == 5);
CHECK(chai.eval<int>("var uptr2 = make_Unique_Ptr_Test_Derived_Class(); uptr2.getI()") == 5);
chai.add(chaiscript::unique_ptr_conversion<Unique_Ptr_Test_Derived_Class, Unique_Ptr_Test_Base_Class>());
chai.add(chaiscript::fun(call_unique_ptr_with_conversion_to_base), "call_unique_ptr_with_conversion_to_base");
CHECK(!chai.eval<bool>("uptr2.is_var_null"));
std::cout << "Attempting conversion" << std::endl;
CHECK_NOTHROW(chai.eval("call_unique_ptr_with_conversion_to_base(uptr2)"));
INFO("Conversion succeeded");
CHECK(chai.eval<bool>("uptr2.is_var_null"));
}