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

Binding a templated method of a templated class - how? #1663

Closed
trexxet opened this issue Jan 5, 2025 · 2 comments
Closed

Binding a templated method of a templated class - how? #1663

trexxet opened this issue Jan 5, 2025 · 2 comments

Comments

@trexxet
Copy link

trexxet commented Jan 5, 2025

Consider a simple templated class that has several templated constructors and methods:

template <typename T>
struct Rect2D {
	T x, y, width, height;

	Rect2D (T _x, T _y, T _w, T _h) : x (_x), y (_y), width (_w), height (_h) {}
	Rect2D () : x (0), y (0), width (0), height (0) {}

	template <typename U>
	Rect2D (T _x, T _y, const Size2D<U>& size) :
		x (_x), y (_y), width (size.width), height (size.height) {}
	
	template <typename U>
	Rect2D (const Point2D<T>& pos, const Size2D<U>& size) :
		x (pos.x), y (pos.y), width (size.width), height (size.height) {}

	template <typename U>
	void centrify (const Rect2D<U>& outer) {
		if (outer.width < width || outer.height < height)
			return;
		x = (outer.width - width) / 2;
		y = (outer.height - height) / 2;
	}

	Point2D<T> pos () { return Point2D<T> {x, y}; }
	Size2D<T> size () { return Size2D<T> {width, height}; }
};

where Size2D<T> = Point2D<T> = struct { T x, y }.

I'm trying to bind it to Lua. Let's sacrifice ability to have U != T in templates, and consider T = U = C. Then, I can do the following:

	auto bindGeometryR2D = [this] <typename C> (const std::string& name) {
		this->state.new_usertype<Rect2D<C>>(name, sol::constructors<
			Rect2D<C>(),
			Rect2D<C>(C, C, C, C),
			Rect2D<C>(C, C, Size2D<C>),
			Rect2D<C>(Point2D<C>, Size2D<C>)>()
		);
	};
	bindGeometryR2D.operator()<int> ("Rect2D");
        bindGeometryR2D.operator()<double> ("Rect2Dd");

Ok, that works fine:

window = Size2D.new(800, 600)
windowRect = Rect2D.new(0, 0, window)

However, I'm struggling to bind the centrify method. Adding after sol::constructors:

"centrify", &Rect2D<C>::centrify

error: no matching function for call to 'sol::state::new_usertype<Based::Rect2D >(const std::string&, sol::constructors< blah blah blah >, <unresolved overloaded function type>)'

Hm, maybe

"centrify", sol::resolve<Rect2D<C>(const Rect2D<C>&)>(&Rect2D<C>::centrify)

error: no matching function for call to 'resolve<Based::Rect2D(const Based::Rect2D&)>(<unresolved overloaded function type>)

So, how should it be done correctly?

Thank you in advance.

@trexxet
Copy link
Author

trexxet commented Jan 6, 2025

Some more findings:

"centrify", &Rect2D<C>::centrify<C>

warning: expected 'template' keyword before dependent template name (???)

@trexxet
Copy link
Author

trexxet commented Jan 6, 2025

Well, the next step solved the issue. Should have listened to the compiler, although at first glance this syntax looks incorrect to me:

"centrify", &Rect2D<C>::template centrify<C>

Quite interesting that if I move the UT outside of the lambda, then the expected syntax from the previous message works fine: &Rect2D<int>::centrify<int>

@trexxet trexxet closed this as completed Jan 6, 2025
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

1 participant