ThePhD / sol2

Sol3 (sol2 v3.0) - a C++ <-> Lua API wrapper with advanced features and top notch performance - is here, and it's great! Documentation:
http://sol2.rtfd.io/
MIT License
4.2k stars 516 forks source link

Overloading vectors #1387

Open maxdemarzi opened 2 years ago

maxdemarzi commented 2 years ago

I was trying to overload a function this way:

    lua.set_function("NodesGet", sol::overload(
        [this](std::vector<uint64_t> ids) { return this->NodesGetViaLua(ids); },
        [this](std::vector<Link> links) { return this->NodesGetByLinksViaLua(links); }
       ));

However it doesn't matter if I send in a vector of uint64_t or Link, it just takes the first entry (uint64_t). I can work around it by manually asking for the inner type of the table and then returning the corresponding function:

sol::as_table_t<std::vector<Node>> Shard::NodesGetOverload(sol::this_state ts, sol::variadic_args args) {
    auto vargs = std::vector<sol::object>(args.begin(), args.end());
    std::vector<std::string> types;
    std::for_each(vargs.begin(), vargs.end(), [&](sol::object obj) {
          const auto type = obj.get_type();
          if (type == sol::type::table) {
              auto table = obj.as<sol::table>();
              if (table.size() > 0) {
                  sol::object inner_type_value = table.get<sol::object>(1);
                  const auto inner_type = inner_type_value.get_type();
                  if(inner_type == sol::type::number) {
                      // We have ids
                      std::vector<uint64_t> ids = obj.as<std::vector<uint64_t>>();
                      return NodesGetViaLua(ids);
                  } else  {
                      // we have links
                      std::vector<Link> links = obj.as<std::vector<Link>>();
                      return NodesGetByLinksViaLua(links);
                  }
              }
          } 
      });
    return sol::as_table(std::vector<Node>());
}

But, please tell me there is a better way to overload vectors arguments... I have a ton of these functions I need to overload.

MJCollett commented 2 years ago

Are the arguments being passed in from Lua already std::vectors, or are they Lua tables that you want converted to vectors? If it's the former, you might try accepting them by const reference rather than by value (which would be more efficient anyway).

maxdemarzi commented 2 years ago

No luck.

    lua.set_function("NodesGet", sol::overload(
        [this](const std::vector<Link>& links) { return this->NodesGetByLinksViaLua(links); },
        [this](const std::vector<uint64_t>& ids) { return this->NodesGetViaLua(ids); }
       ));

Gives me:

sol: no matching function call takes this number of arguments and the specified types

And:

lua.set_function("NodesGet", sol::overload(
    [this](std::vector<Link> links) { return this->NodesGetByLinksViaLua(links); },
    [this](std::vector<uint64_t> ids) { return this->NodesGetViaLua(ids); }
   ));

Gives me this error when I try to pass uint64s:

An exception has occurred: stack index -1, expected userdata, received number: value is not a valid userdata

Any other ideas?