Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Shareable metafunctions and metafunctions for more than just types #1350

Unanswered
LouChiSoft asked this question in Q&A
Discussion options

Metafunctions are probably my favourite feature in Cpp2 and I know that there is work being done to allow users to define their own custom metafunctions. But I was wondering if there had been any talk about how they could be shared. Is it going to be a source code only kind of thing? Or maybe you can get a metafunction in some kind of compiled function that is ran by the compiler at compile time.

I was also wondering if there have been discussions about enabling the user of metafunctions for more than just a type definition. The use case I am thinking of comes from things like Unreal and Godot. Both engines make use of macros in both their C++ APIs to add the required boiler plate code for various things in a class.

Unreal example:

UCLASS()
class ATestCharacter: public ACharacter
{
 GENERATED_BODY()
 public:
 // Public member function to get health
 UFUNCTION(BlueprintPure, Category = "Health")
 float GetHealth() const;
 
 // Public member function to set health
 UFUNCTION(BlueprintCallable, Category = "Health")
 void SetHealth(float NewHealth);
 
 protected:
 // Protected member variable
 UPROPERTY(EditDefaultsOnly, Category = "Health")
 float Health;
};

It would be interesting to see metafunctions be usable inside a class to replace the properties as well. e.g.

// In this example there isn't much different in terms of line count, but it does remove calls to the 
// pre-processor and also removes the GENERATE_BODY macro which would be part of 
// the @UnrealClass metafunction
ATestCharacter: @UnrealClass<ACharacter> type = {
 public :
 GetHealth: @UFunction<BlueprintPure, Category = "Health">(this) const -> float;
 SetHealth: @UFunction<BlueprintPure, Category = "Health">(this, NewHealth: float);
 protected:
 health: @UProperty<EditDefaultsOnly, Category = "Health"> float;
}

Not a fully indepth example, and I am sure there will be syntax errors in there but it demonstrates the intent. With Godot it could be even more useful, since in Godot when you want to expose a value in the editor you not only have to manyally define a getter and setter like Unreal, but you then have to manually write a _bind_methods_ function where you bind the methods to the property in question so the editor can read and write them, e.g.

Godot example:

class Component : public godot::Resource {
 GDCLASS(Component, godot::Resource)
public:
 auto get_position() const -> godot::Vector3 { return _position; }
 auto set_position(const godot::Vector3& p) -> void { _position = p; }
protected:
 static auto _bind_methods() -> void {
 using namespace godot;
 ClassDB::bind_method(D_METHOD("get_position"), &Component::get_position);
 ClassDB::bind_method(D_METHOD("set_position", "position"), &Component::set_position);
 ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position"), "set_position", "get_position");
 }
private:
 godot::Vector3 _position;
};

Could become:

// This example is a more drastic improvement, with a much lower line count, by making the GDCLASS
// macro call a type metafunction and in this example it assumes that the @Property metafunction
// would generate a _bind_methods function for you based on the parameters pass to the
// metafunction and the property type. For a more complete behaviour, multiple @Property functions
// would be able to combine into the single _bind_methods function that is needed by an exposed godot
// class. Could maybe be achieved by having the @GDClass metafunction keep track of all the @Property
// metafunction calls and then combining the outputs of all of them
Component: @GDClass<godot::Resource> type = {
public:
 get_position: (this) const -> godot::Vector3 = { return _position }
 set_position: (this, p: const godot::Vector3) = { this._position = p; }
private:
 _position: @Property<get_position, set_position> godot::Vector3;
}

Again, almost certain has syntax errors, sorry. But I still think there is potential here for more than just type defintion metafunctions and can feature as a more fully feature replacement to the pre-processor which doesn't exist in non-backwards compatible Cpp2.

Any thoughts?

You must be logged in to vote

Replies: 1 comment 1 reply

Comment options

Some related conversations:

You must be logged in to vote
1 reply
Comment options

Thanks for the list. Awesome that the shareable metafunctions are being considered as well as expending metafunctions for more than just classes. While I am sure there is concern about overuse of a metafunction system, in order to entirely replace the pre-processor in Cpp1 I think they are neded and being able to share pre-compiled metafunctions that are just part of the library seems like a great way to share them

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants

AltStyle によって変換されたページ (->オリジナル) /