Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
December 30, 2014 Define methods using templates | ||||
---|---|---|---|---|
| ||||
Hello, I'm trying to use templates to define several methods (property setters) within a class to avoid some code duplication. Here is an attempt: class Camera { private: Vector4 m_pos; float m_fov, m_ratio, m_near, m_far; bool m_matrixCalculated; public: void SetProperty(Tin, alias Field)(ref Tin param) @property pure @safe { Field = param; m_matrixCalculated = false; } alias pos = SetProperty!(float[], m_pos); alias pos = SetProperty!(Vector4, m_pos); alias ratio = SetProperty!(float, m_ratio); alias near = SetProperty!(float, m_near); alias far = SetProperty!(float, m_far); } I get this kind of compilation error: Error: template instance SetProperty!(float[], m_pos) cannot use local 'm_pos' as parameter to non-global template SetProperty(Tin, alias Field)(ref Tin param) I don't understand why that error occurs. And I cannot find any elegant solutions (even with mixin's) to declare a template and then instantiate it in a single line to define the methods I want. Does any of you have an idea? Thanks |
December 30, 2014 Re: Define methods using templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Claude | On 12/30/14 8:17 AM, Claude wrote:
> Hello, I'm trying to use templates to define several methods (property
> setters) within a class to avoid some code duplication.
> Here is an attempt:
>
> class Camera
> {
> private:
> Vector4 m_pos;
> float m_fov, m_ratio, m_near, m_far;
> bool m_matrixCalculated;
>
> public:
> void SetProperty(Tin, alias Field)(ref Tin param) @property pure @safe
> {
> Field = param;
> m_matrixCalculated = false;
> }
>
> alias pos = SetProperty!(float[], m_pos);
> alias pos = SetProperty!(Vector4, m_pos);
> alias ratio = SetProperty!(float, m_ratio);
> alias near = SetProperty!(float, m_near);
> alias far = SetProperty!(float, m_far);
> }
>
> I get this kind of compilation error:
> Error: template instance SetProperty!(float[], m_pos) cannot use local
> 'm_pos' as parameter to non-global template SetProperty(Tin, alias
> Field)(ref Tin param)
>
> I don't understand why that error occurs.
I think it has to do with the fact that when you are defining the aliases, m_pos for example, is an *instance* member so requires an instance to get an alias.
What you are probably better off doing is:
void SetProperty(Tin, string Field)(ref Tin param) @property pure @safe
{
mixin(Field ~ " = param;");
m_matrixCalculated = false;
}
alias pos = SetProperty!(float[], "m_pos");
I would also put some strict template constraints on the Field string too, because one abuse SetProperty pretty easily there.
-Steve
|
December 30, 2014 Re: Define methods using templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 12/30/14 8:48 AM, Steven Schveighoffer wrote:
> I think it has to do with the fact that when you are defining the
> aliases, m_pos for example, is an *instance* member so requires an
> instance to get an alias.
>
> What you are probably better off doing is:
>
> void SetProperty(Tin, string Field)(ref Tin param) @property pure @safe
> {
> mixin(Field ~ " = param;");
> m_matrixCalculated = false;
> }
>
> alias pos = SetProperty!(float[], "m_pos");
>
> I would also put some strict template constraints on the Field string
> too, because one abuse SetProperty pretty easily there.
A possibly more elegant solution, use opDispatch:
void opDispatch(string Field, Tin)(ref Tin param) @property pure @safe if(Field == "pos" || Field == "ratio" || ...)
{
mixin("m_" ~ Field ~ " = param;");
m_matrixCalculated = false;
}
Not sure if opDispatch works as a @property this way...
-Steve
|
December 30, 2014 Re: Define methods using templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Claude | V Tue, 30 Dec 2014 13:17:08 +0000 Claude via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> napsáno: > Hello, I'm trying to use templates to define several methods (property setters) within a class to avoid some code duplication. Here is an attempt: > > class Camera > { > private: > Vector4 m_pos; > float m_fov, m_ratio, m_near, m_far; > bool m_matrixCalculated; > > public: > void SetProperty(Tin, alias Field)(ref Tin param) @property > pure @safe > { > Field = param; > m_matrixCalculated = false; > } > > alias pos = SetProperty!(float[], m_pos); > alias pos = SetProperty!(Vector4, m_pos); > alias ratio = SetProperty!(float, m_ratio); > alias near = SetProperty!(float, m_near); > alias far = SetProperty!(float, m_far); > } > > I get this kind of compilation error: > Error: template instance SetProperty!(float[], m_pos) cannot use > local 'm_pos' as parameter to non-global template > SetProperty(Tin, alias Field)(ref Tin param) > > I don't understand why that error occurs. > > And I cannot find any elegant solutions (even with mixin's) to declare a template and then instantiate it in a single line to define the methods I want. > > Does any of you have an idea? > > Thanks class Camera { private: int m_pos; float m_fov, m_ratio, m_near, m_far; bool m_matrixCalculated; public: mixin template opAssign(alias Field) { void opAssign(Tin)(auto ref Tin param) @property pure @safe { Field = param; m_matrixCalculated = false; } } mixin opAssign!(m_pos) pos; mixin opAssign!(m_fov) fov; mixin opAssign!(m_ratio) ratio; mixin opAssign!(m_near) near; mixin opAssign!(m_far) far; } void main() { Camera cam = new Camera(); cam.fov = 1.0; stdin.readln; } |
December 30, 2014 Re: Define methods using templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Kozák | Thanks Steven and Daniel for your explanations.
> mixin template opAssign(alias Field) {
> void opAssign(Tin)(auto ref Tin param) @property pure @safe
> {
> Field = param;
> m_matrixCalculated = false;
> }
> }
>
> mixin opAssign!(m_pos) pos;
I tested both the "string mixin" and "opAssign" implementations, and they work like a charm.
I would have never thought of using both @property and "opAssign", but it looks like a secure way of doing it for the compilation fails nicely if I type a wrong field in.
src/camera.d(58): Error: undefined identifier m_os, did you mean variable m_pos?
|
December 30, 2014 Re: Define methods using templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Claude | On 12/30/2014 05:17 AM, Claude wrote: > use templates to define several methods (property > setters) within a class to avoid some code duplication. I just saw this post, which is essentially the same question as Basile Burg's. I hope that a college (in France?) is teaching D and that this is a homework assignment. Cool stuff! :) Ali |
January 08, 2015 Re: Define methods using templates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | > I just saw this post, which is essentially the same question as Basile Burg's. I hope that a college (in France?) is teaching D and that this is a homework assignment. Cool stuff! :)
Maybe using templates to create properties is a bit overkill in this example. But I could not solve what I thought would be a very simple and straightforward "template use-case" (initially I'm an embedded RT system C/asm developer).
I'm doing this for a personal project of a 3D engine. As I know little about C++/Java or other OO language, I thought I would do it directly in D, which seems very promising to me (but unfortunately not taught in France as far as I know).
|
Copyright © 1999-2021 by the D Language Foundation