Merge pull request #243 from vrennert/feature_initializer_list_conversion
Added initializer_list<T> conversion as possible function call argument or return type.
This commit is contained in:
commit
f697384028
@ -310,7 +310,48 @@ namespace chaiscript
|
|||||||
private:
|
private:
|
||||||
Callable m_func;
|
Callable m_func;
|
||||||
};
|
};
|
||||||
|
#ifndef CHAISCRIPT_MSVC_12
|
||||||
|
//http://stackoverflow.com/questions/18895583/convert-a-vectort-to-initializer-listt
|
||||||
|
constexpr size_t DEFAULT_MAX_LENGTH = 128;
|
||||||
|
|
||||||
|
template <typename V> struct backingValue { static V value; };
|
||||||
|
template <typename V> V backingValue<V>::value;
|
||||||
|
|
||||||
|
template <typename V, typename... Vcount> struct backingList { static std::initializer_list<V> list; };
|
||||||
|
template <typename V, typename... Vcount>
|
||||||
|
std::initializer_list<V> backingList<V, Vcount...>::list = { (Vcount)backingValue<V>::value... };
|
||||||
|
|
||||||
|
template <size_t maxLength, typename It, typename V = typename It::value_type, typename... Vcount>
|
||||||
|
static typename std::enable_if< sizeof...(Vcount) >= maxLength,
|
||||||
|
std::initializer_list<V> >::type generate_n(It begin, It end, It current)
|
||||||
|
{
|
||||||
|
throw std::length_error("More than maxLength elements in range.");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <size_t maxLength = DEFAULT_MAX_LENGTH, typename It, typename V = typename It::value_type, typename... Vcount>
|
||||||
|
static typename std::enable_if< sizeof...(Vcount) < maxLength,
|
||||||
|
std::initializer_list<V> >::type generate_n(It begin, It end, It current)
|
||||||
|
{
|
||||||
|
if (current != end)
|
||||||
|
{
|
||||||
|
return generate_n<maxLength, It, V, V, Vcount...>(begin, end, ++current);
|
||||||
|
}
|
||||||
|
|
||||||
|
current = begin;
|
||||||
|
for (auto it = backingList<V, Vcount...>::list.begin();
|
||||||
|
it != backingList<V, Vcount...>::list.end();
|
||||||
|
++current, ++it)
|
||||||
|
*const_cast<V*>(&*it) = *current;
|
||||||
|
|
||||||
|
return backingList<V, Vcount...>::list;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename It>
|
||||||
|
std::initializer_list<typename It::value_type> range_to_initializer_list(It begin, It end)
|
||||||
|
{
|
||||||
|
return detail::generate_n(begin, end, begin);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
class Type_Conversions
|
class Type_Conversions
|
||||||
@ -582,7 +623,7 @@ namespace chaiscript
|
|||||||
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
|
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
|
||||||
|
|
||||||
To vec;
|
To vec;
|
||||||
|
vec.reserve(from_vec.size());
|
||||||
for (const Boxed_Value &bv : from_vec) {
|
for (const Boxed_Value &bv : from_vec) {
|
||||||
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
|
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
|
||||||
}
|
}
|
||||||
@ -593,6 +634,26 @@ namespace chaiscript
|
|||||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
|
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_MSVC_12
|
||||||
|
template<typename To>
|
||||||
|
Type_Conversion initializer_list_conversion()
|
||||||
|
{
|
||||||
|
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||||
|
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
|
||||||
|
|
||||||
|
std::vector<typename To::value_type> vec;
|
||||||
|
vec.reserve(from_vec.size());
|
||||||
|
for (const auto &bv : from_vec)
|
||||||
|
{
|
||||||
|
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Boxed_Value(detail::range_to_initializer_list(vec.begin(), vec.end()));
|
||||||
|
};
|
||||||
|
auto ret = chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1005,6 +1005,7 @@ namespace chaiscript
|
|||||||
try {
|
try {
|
||||||
std::vector<Boxed_Value> vec;
|
std::vector<Boxed_Value> vec;
|
||||||
if (!children.empty()) {
|
if (!children.empty()) {
|
||||||
|
vec.reserve(children[0]->children.size());
|
||||||
for (const auto &child : children[0]->children) {
|
for (const auto &child : children[0]->children) {
|
||||||
auto obj = child->eval(t_ss);
|
auto obj = child->eval(t_ss);
|
||||||
if (!obj.is_return_value()) {
|
if (!obj.is_return_value()) {
|
||||||
|
@ -913,3 +913,46 @@ TEST_CASE("Return of converted type from script")
|
|||||||
chai.add(chaiscript::user_type<Returned_Converted_Config>(), "Returned_Converted_Config");
|
chai.add(chaiscript::user_type<Returned_Converted_Config>(), "Returned_Converted_Config");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CHAISCRIPT_MSVC_12
|
||||||
|
TEST_CASE("Return initializer_list")
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
|
chai.add(chaiscript::initializer_list_conversion<std::initializer_list<int>>());
|
||||||
|
|
||||||
|
auto initlist = chai.eval<std::initializer_list<int>>(R"(
|
||||||
|
return [11, 22, 33, 44];
|
||||||
|
)");
|
||||||
|
|
||||||
|
CHECK(initlist.size() == 4);
|
||||||
|
CHECK(typeid(decltype(initlist)) == typeid(std::initializer_list<int>));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool initializer_list_of_enums_interface(std::initializer_list<Utility_Test_Numbers> initlist)
|
||||||
|
{
|
||||||
|
return initlist.size() == 3 && *initlist.begin() == THREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Call from script with initializer_list argument")
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
|
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
|
||||||
|
chaiscript::utility::add_class<Utility_Test_Numbers>(*m,
|
||||||
|
"Utility_Test_Numbers",
|
||||||
|
{ { ONE, "ONE" },
|
||||||
|
{ TWO, "TWO" },
|
||||||
|
{ THREE, "THREE" }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
chai.add(m);
|
||||||
|
|
||||||
|
chai.add(chaiscript::initializer_list_conversion<std::initializer_list<Utility_Test_Numbers>>());
|
||||||
|
chai.add(chaiscript::fun(&initializer_list_of_enums_interface), "initializer_list_of_enums_interface");
|
||||||
|
|
||||||
|
auto interface_result = chai.eval<bool>("return initializer_list_of_enums_interface([THREE, TWO, ONE]);");
|
||||||
|
|
||||||
|
CHECK(interface_result == true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user