Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting compilation error when registering type #1610

Closed
sanjuchopracool opened this issue Jun 17, 2024 · 4 comments
Closed

Getting compilation error when registering type #1610

sanjuchopracool opened this issue Jun 17, 2024 · 4 comments

Comments

@sanjuchopracool
Copy link

sanjuchopracool commented Jun 17, 2024

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 sanjuchopracool changed the title Getting compilation error with magnum vector type Getting compilation error when registering type Jun 17, 2024
@sanjuchopracool
Copy link
Author

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
Copy link

Rochet2 commented Jun 19, 2024

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);

@matusnovak
Copy link

matusnovak commented Jul 17, 2024

I started having this same issue after upgrading to clang 18.1.8

The above fix with sol::resolve nor static_cast worked for me. The sol::property workaround by @sanjuchopracool was the only solution.

I have made a templated wrapper to make it simpler to apply

template <typename V, typename C, V C::*Ptr> static auto asLuaPropertyInternal() {
    return sol::property(
        [](C& type) { return (type.*Ptr); },
        [](C& type, const V& val) { (type.*Ptr) = val; }
    );
}

template <typename M> struct GetPointerType {
    // No need to define this function, may raise a compile or linter warning
    template <typename C, typename T> static T getType(T C::*v);

    typedef decltype(getType(static_cast<M>(nullptr))) type;
};

template <typename Var, Var var> struct GetVarTraits;

template <typename C, typename T, T C::*Var> struct GetVarTraits<T C::*, Var> {
    using klass = C;
};

template <auto Field> static auto asLuaProperty() {
    // Figure out the type of the "Field"
    using V = typename GetPointerType<decltype(Field)>::type;
    // Figure out the class type which this "Field" belongs to
    using C = typename GetVarTraits<decltype(Field), Field>::klass;

    return asLuaPropertyInternal<V, C, Field>();
}

#define LUA_PROP(Var) asLuaProperty<Var>()

And then to use it:

my_vec2_type["x"] = LUA_PROP(&MyVec2D::x);

Should also work with Visual Studio's MSVC Clang

@sanjuchopracool
Copy link
Author

@matusnovak I was getting similar problems with some other data types and tried your wrapper. But got compilation errors with msvc

C:\Users\sanju\PROJECTS\inae\src\inae_core\src\core\script_sandbox\main.cpp(115): error C2672: 'asLuaProperty': no matching overloaded function found
C:\Users\sanju\PROJECTS\inae\src\inae_core\src\core\script_sandbox\main.cpp(80): note: could be 'auto asLuaProperty(void)'
C:\Users\sanju\PROJECTS\inae\src\inae_core\src\core\script_sandbox\main.cpp(79): note: 'Field': cannot deduce the type of the placeholder
C:\Users\sanju\PROJECTS\inae\src\inae_core\src\core\script_sandbox\main.cpp(115): note: cannot deduce type for 'auto' from 'overloaded-function'
C:\Users\sanju\PROJECTS\inae\src\inae_core\src\core\script_sandbox\main.cpp(115): note: 'Field': invalid template argument for 'asLuaProperty', expected compile-time constant expression

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants