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

Getting compilation error when registering type #1610

Open sanjuchopracool opened 2 weeks ago

sanjuchopracool commented 2 weeks ago

I am getting compilation error when I try to register member function x and y for MyVector class. I think it's happening because of const member function overload.

#include <sol/sol.hpp>

// Small example class  similar to magnum vector2
template<std::size_t size, class T>
class MyVector
{
protected:
    T _data[size];
};

template<typename T>
class MyVector2 : public MyVector<2, T>
{
public:
    T &x() { return MyVector<2, T>::_data[0]; }
    const T &x() const { return MyVector<2, T>::_data[0]; }
    T &y() { return MyVector<2, T>::_data[1]; }
    const T &y() const { return MyVector<2, T>::_data[1]; }
};

int main()
{
    sol::state lua;
    lua.open_libraries(sol::lib::base, sol::lib::package);

    using MyVec2D = MyVector2<float>;
    MyVec2D my_vec;

    // Gives compilation error
    sol::usertype<MyVec2D> my_vec2_type = lua.new_usertype<MyVec2D>("MyVec2D",
                                                                    sol::constructors<MyVec2D()>());
    my_vec2_type["x"] = &MyVec2D::x;

    return 0;
}

The error I am getting are

Building CXX object src/CMakeFiles/MyApplication.dir/MyApplication.cpp.o
/Users/sanju/PROJECTS/magnum-lua-build/src/MyApplication.cpp:31:23: error: no viable overloaded '='
    my_vec2_type["x"] = &MyVec2D::x;
    ~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~
/Users/sanju/PROJECTS/magnum-lua-build/lua/sol/sol.hpp:24900:19: note: candidate template ignored: couldn't infer template argument 'T'
                usertype_proxy& operator=(T&& other) & {
                                ^
/Users/sanju/PROJECTS/magnum-lua-build/lua/sol/sol.hpp:24905:20: note: candidate template ignored: couldn't infer template argument 'T'
                usertype_proxy&& operator=(T&& other) && {
                                 ^
/Users/sanju/PROJECTS/magnum-lua-build/lua/sol/sol.hpp:24910:19: note: candidate template ignored: couldn't infer template argument 'T'
                usertype_proxy& operator=(std::initializer_list<T> other) & {
                                ^
/Users/sanju/PROJECTS/magnum-lua-build/lua/sol/sol.hpp:24915:20: note: candidate template ignored: couldn't infer template argument 'T'
                usertype_proxy&& operator=(std::initializer_list<T> other) && {
                                 ^
/Users/sanju/PROJECTS/magnum-lua-build/lua/sol/sol.hpp:24843:9: note: candidate function (the implicit copy assignment operator) not viable: no overload of 'x' matching 'const sol::usertype_proxy<sol::basic_usertype<MyVector2<float>, sol::basic_reference<false>> &, const char *>' for 1st argument
        struct usertype_proxy : public proxy_base<usertype_proxy<Table, Key>> {
               ^
1 error generated.

I tried multiple things to make it work, but did not work. Is there any way to register the functions MyVector2::x() ?

sanjuchopracool commented 2 weeks ago

I have this workaround

    my_vec2_type.set("x",
                     sol::property([](MyVec2D &type) { return type.x(); },
                                   [](MyVec2D &type, float val) { type.x() = val; }));
    my_vec2_type.set("y",
                     sol::property([](MyVec2D &type) { return type.y(); },
                                   [](MyVec2D &type, float val) { type.y() = val; }));

I can't change the original class, because it's third party comes from Magnum library. Is there any better solution for it ?

Rochet2 commented 2 weeks ago

There are basically multiple possible definitions and you need to choose one. You can use a static cast or a sol helper function sol::resolve to specify the one you want.

Examples:

    my_vec2_type["x"] = sol::resolve<float& ()>(&MyVec2D::x);
    my_vec2_type["y"] = static_cast<float&(MyVec2D::*)()>(&MyVec2D::y);