#define SOL_CHECK_ARGUMENTS 1 #include #include #include #include int main(int argc, char** argv) { std::cout << "=== optional and iteration example ===" << std::endl; struct thing { int a = 20; thing() = default; thing(int a) : a(a) {} }; struct super_thing : thing { int b = 40; }; struct unrelated { }; sol::state lua; // Comment out the new_usertype call // to prevent derived class "super_thing" // from being picked up and cast to its base // class lua.new_usertype("super_thing", sol::base_classes, sol::bases() ); // Make a few things lua["t1"] = thing{}; lua["t2"] = super_thing{}; lua["t3"] = unrelated{}; // And a table lua["container"] = lua.create_table_with( 0, thing{50}, 1, unrelated{}, 4, super_thing{} ); std::vector> things; // Our recursive function // We use some lambda techniques and pass the function itself itself so we can recurse, // but a regular function would work too! auto fx = [&lua, &things](auto& f, auto& tbl) -> void { // You can iterate through a table: it has // begin() and end() // like standard containers for (auto key_value_pair : tbl) { // Note that iterators are extremely frail // and should not be used outside of // well-constructed for loops // that use pre-increment ++, // or C++ ranged-for loops const sol::object& key = key_value_pair.first; const sol::object& value = key_value_pair.second; sol::type t = value.get_type(); switch (t) { case sol::type::table: f(f, value.as()); break; case sol::type::userdata: { // This allows us to check if a userdata is // a specific class type sol::optional maybe_thing = value.as>(); if (maybe_thing) { thing& the_thing = maybe_thing.value(); if (key.is()) { std::cout << "key " << key.as() << " is a thing -- "; } else if (key.is()) { std::cout << "key " << key.as() << " is a thing -- "; } std::cout << "thing.a ==" << the_thing.a << std::endl; things.push_back(the_thing); } } break; default: break; } } }; fx(fx, lua); std::cout << std::endl; return 0; }