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.06k stars 492 forks source link

std::variant, float-int, loss of type #1524

Open ensisoft opened 10 months ago

ensisoft commented 10 months ago

Hello all

seems like using std::variant there's some loss of precise typing.

consider

#  define SOL_ALL_SAFETIES_ON 1
#  include <sol/sol.hpp>

#include <variant>
#include <string>

int main()
{
    sol::state lua;
    lua.open_libraries();

    using Variant = std::variant<float, int, std::string>;

    Variant the_value;
    lua["set_the_variant"] = [&the_value](Variant val) {
        if (const auto* p = std::get_if<int>(&val))
            std::cout << "int\n";
        else if (const auto* p = std::get_if<float>(&val))
            std::cout << "float\n";
        the_value = val;
    };
    lua["get_the_variant"] = [&the_value]() {
        return the_value;
    };

    lua.script(R"(
set_the_variant(123)
print(get_the_variant())
)");

integer type is lost and the variant is stored as float.

I did a bunch of other tests and if you write an int the the variant in native code and read it in Lua you get an int.

Is this a bug or a feature?

deadlocklogic commented 7 months ago

Neither a bug, nor a feature: It is the expected behavior. This is a fundamental Lua behavior, Lua has no concept of integer type, every integer pushed to Lua (by the C API) will be stored as a double-precision floating-point. Check Number

The number type represents real (double-precision floating-point) numbers. Lua has no integer type, as it does not need it.

This is similar to Javascript too.

ensisoft commented 7 months ago

@deadlocklogic in the C API level Lua has both integers (lua_Integer) as well as floats (lua_Number) and since Lua 5.3 even the Lua programmer can choose between the internal sub type representation.

deadlocklogic commented 7 months ago

A quick test As you may see:

print(math.type(123)) -- integer
print(type(math.tointeger(123))) -- number
print(type(123)) -- number

And Lua 5.3:

There are eight basic types in Lua: nil, boolean, number, string, function, userdata, thread, and table.

So nothing fundamental changed, integers are still a number type but it added 64 bit representation for better precision, you have to use the C API yourself to check if a number is an integer or not. Your example can be better written like this: Example