diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index bc3c0869..2c45d4a3 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -31,7 +31,7 @@ #include "register_function.hpp" #include "type_info.hpp" -namespace chaiscript +namespace chaiscript { namespace bootstrap { @@ -219,6 +219,51 @@ namespace chaiscript } + /// Add random_access_advance_container concept to the given ContainerType, using advance. + /// http://www.sgi.com/tech/stl/RandomAccessContainer.html + template + void random_access_advance_container_type(const std::string &/*type*/, Module& m) + { + //In the interest of runtime safety for the m, we prefer the at() method for [] access, + //to throw an exception in an out of bounds condition. + m.add( + fun( + [](ContainerType &c, int index) -> typename ContainerType::reference { + /// \todo we are prefering to keep the key as 'int' to avoid runtime conversions + /// during dispatch. reevaluate + auto itr = c.begin(); + auto end = c.end(); + if (index < 0 || std::distance(itr, end) < index) + { + throw std::range_error("Desired index out of range"); + } + std::advance(itr, index); + return *itr; + }), "[]"); + + m.add( + fun( + [](const ContainerType &c, int index) -> typename ContainerType::const_reference { + /// \todo we are prefering to keep the key as 'int' to avoid runtime conversions + /// during dispatch. reevaluate + auto itr = c.begin(); + auto end = c.end(); + if (index < 0 || std::distance(itr, end) < index) + { + throw std::range_error("Desired index out of range"); + } + std::advance(itr, index); + return *itr; + }), "[]"); + } + template + ModulePtr random_access_advance_container_type(const std::string &type) + { + auto m = std::make_shared(); + random_access_advance_container_type(type, *m); + return m; + } + /// Add assignable concept to the given ContainerType /// http://www.sgi.com/tech/stl/Assignable.html @@ -335,7 +380,7 @@ namespace chaiscript template void back_insertion_sequence_type(const std::string &type, Module& m) { - m.add(fun([](ContainerType &container)->decltype(auto){ + m.add(fun([](ContainerType &container)->decltype(auto){ if (container.empty()) { throw std::range_error("Container empty"); } else { @@ -344,7 +389,7 @@ namespace chaiscript } ) , "back"); - m.add(fun([](const ContainerType &container)->decltype(auto){ + m.add(fun([](const ContainerType &container)->decltype(auto){ if (container.empty()) { throw std::range_error("Container empty"); } else { @@ -398,7 +443,7 @@ namespace chaiscript typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference); typedef void (ContainerType::*pop_ptr)(); - m.add(fun([](ContainerType &container)->decltype(auto){ + m.add(fun([](ContainerType &container)->decltype(auto){ if (container.empty()) { throw std::range_error("Container empty"); } else { @@ -408,7 +453,7 @@ namespace chaiscript ) , "front"); - m.add(fun([](const ContainerType &container)->decltype(auto){ + m.add(fun([](const ContainerType &container)->decltype(auto){ if (container.empty()) { throw std::range_error("Container empty"); } else { @@ -559,7 +604,7 @@ namespace chaiscript } } )" ); - } + } container_type(type, m); default_constructible_type(type, m); @@ -591,6 +636,7 @@ namespace chaiscript default_constructible_type(type, m); assignable_type(type, m); input_range_type(type, m); + random_access_advance_container_type(type, m); } template ModulePtr list_type(const std::string &type) @@ -608,7 +654,7 @@ namespace chaiscript { m.add(user_type(), type); - m.add(fun([](VectorType &container)->decltype(auto){ + m.add(fun([](VectorType &container)->decltype(auto){ if (container.empty()) { throw std::range_error("Container empty"); } else { @@ -618,7 +664,7 @@ namespace chaiscript ) , "front"); - m.add(fun([](const VectorType &container)->decltype(auto){ + m.add(fun([](const VectorType &container)->decltype(auto){ if (container.empty()) { throw std::range_error("Container empty"); } else { @@ -663,7 +709,7 @@ namespace chaiscript } } )" ); - } + } } template ModulePtr vector_type(const std::string &type) @@ -706,7 +752,7 @@ namespace chaiscript m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_of(f, pos); } ), "find_last_of"); m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_last_not_of(f, pos); } ), "find_last_not_of"); m.add(fun([](const String *s, const String &f, size_t pos) { return s->find_first_not_of(f, pos); } ), "find_first_not_of"); - + m.add(fun([](String *s, typename String::value_type c) -> decltype(auto) { return (*s += c); } ), "+="); m.add(fun([](String *s) { s->clear(); } ), "clear"); diff --git a/unittests/list_push_back.chai b/unittests/list_push_back.chai index 35b8fa68..d172eaab 100644 --- a/unittests/list_push_back.chai +++ b/unittests/list_push_back.chai @@ -7,6 +7,5 @@ x.push_back("A") assert_equal(3, x.front()); assert_equal("A", x.back()); - - - +// Random access with List objects. +assert_equal("A", x[1])