#define SOL_ALL_SAFETIES_ON 1 #include #include #include #include struct thing { int a = 20; thing() = default; thing(int a) : a(a) { } }; struct super_thing : thing { int b = 40; }; struct unrelated { }; int main(int, char*[]) { std::cout << "=== optional with iteration ===" << std::endl; 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 = [&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: { sol::table inner = value.as(); f(f, inner); } 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; }