Sol2: Enum types

Created on 25 May 2016  路  13Comments  路  Source: ThePhD/sol2

Enum types can be easily simulated by doing something like this \/

C++:

enum Direction {
    UP = 0,
    RIGHT,
    DOWN,
    LEFT,
};

void showEnum(int direction) {
    static_cast<Direction>(direction);
}

lua.set_function("showEnum", &showEnum);

Lua:

local Direction = {
    UP = 0,
    RIGHT = 1,
    DOWN = 2,
    LEFT = 3
}

showEnum(Direction.DOWN)

It's not a great thing, i know
But, this will be possible in future releases? \/

C++:

enum Direction {
    UP = 0,
    RIGHT,
    DOWN,
    LEFT,
};

void showEnum(Direction direction) {
    direction;
}

lua.new_usertype<Direction>("Dir",
                            "UP", &Direction::UP,
                            "RIGHT", &Direction::RIGHT,
                            "DOWN", &Direction::DOWN,
                            "LEFT", &Direction::LEFT);

Lua:
showEnum(Direction.UP)

Bike.Shed Feature.Already Done

Most helpful comment

@EliasD

It seems to work

Obligatory warning that making it "read-only" has a performance overhead etc. etc., if read-only bothers you call new_enum<false> to trigger a read/write table (that's just a regular table with no fancy metatable stuff).

All 13 comments

enum class Direction {
     Up,
     Right,
     Down,
     Left
}

sol::state lua;

lua["Direction"] = lua.create_table_with( 
     "Up", Direction::Up, 
     "Down", Direction::Down, 
     "Left", Direction::Left, 
     "Right", Direction::Right 
);

Should work? If it doesn't, let me know.

Yes, it worked, of course, nice :)

Maybe a note in the tutorial about it?
probably others will question about it like me ;-/

I've tried this too and this works:

sol::object obj = lua["Direction"]["Up"];
auto dir = obj.as<Direction>();

but obj.is<Direction> returns false. If I try to register Direction as usertype, obj.as<Direction>() fails. What can be done about this?

auto dir = static_cast<Direction>(obj.as<int>());

That was a small oversight of mine. I have forgotten traits specifically for converting enum class types and the like (and plain enum, without the class, were treated like integers). Pushing the fix today, along with about 20 other things...

Summer school. q_q

It also seems like a convenience function

lua.create_enum( "enum_name",
    "val1", my_enum::val1,
    "val2", my_enum::val2,
    "val3", my_enum::val3,
    "val4", my_enum::val4
    // ...
);

would be nice.

Wow, thanks! That was quicker then I expected. I'll test it later. :)

create_enum function would indeed be very useful. It would be also great to automatically make "enum_name" table read only. Accidentally changing or adding/removing some values in that table will lead to some bad stuff.

@EliasD

It seems to work

Obligatory warning that making it "read-only" has a performance overhead etc. etc., if read-only bothers you call new_enum<false> to trigger a read/write table (that's just a regular table with no fancy metatable stuff).

I don't think this was ever documented.

You're right, it hasn't been, I forgot. I guess I'll get on it.

Is there a way to quickly register a large enum (that supports iteration and to_string conversion) without explicitly touching every element?
Long version example:

lua.new_enum("ItemType",
    "Weapon", ItemType::Weapon,
    "Armor", ItemType::Armor,
    "Potion", ItemType::Potion,
    "Misc", ItemType::Misc
);

Once this enum gets bigger, I'd need to add the elements there (which I want to avoid).

Unfortunately, no. Sol does not do auto-binding (yet).

The only way to do automatic iteration is to require the user to pick one of many available reflection libraries out there (Boost.Fusion / libmirror), force the user to annotate their types, and then hook into those structures. This is a bit of a daunting task.

The other way would be to use a parser of some sort to read C++ source and then just bind All The Things. The problem with this approach is that now I need to build a C++ parser into Sol at runtime. That would make the library a humongous pain for both end users to use (ease of use for people to install Sol, executable size, and other things) and a problem for me (I'm building the early stages of a compiler. Aaahhh, the BUGS).

The good news is, Sol can be used with other generators. That is, there's no harm in grabbing, say, SWIG to do some rudimentary bindings for enums and other types while Sol just helps you manage state and register smaller, concise usertypes.

I know this answer isn't satisfactory. I don't like it myself, to be quite frank: problem is, my hands are tied until C++??, when I can take a hard dependency on built-in reflection. I'm going to hope it's before C++20.

Oh, ok thx :D @eliasdaler suggested the following to be. Maybe someone else will find it usefull, too:

sol::table enumTable = lua["SomeEnumName"];
for(auto& enumValue : enumValues)
    enumTable [to_string(enumValue)] = enumValue

EDIT: Of course this should be done after loading the script (not like the registration through new_enum)... which's makes this solution not that great either.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

karenzshea picture karenzshea  路  4Comments

elfring picture elfring  路  10Comments

squeek502 picture squeek502  路  4Comments

cgloeckner picture cgloeckner  路  3Comments

sagunkho picture sagunkho  路  4Comments