www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Define methods using templates

reply "Claude" <claudemr live.fr> writes:
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
Dec 30 2014
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Dec 30 2014
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
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
Dec 30 2014
prev sibling next sibling parent reply Daniel =?UTF-8?B?S296w6Fr?= via Digitalmars-d-learn writes:
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; }
Dec 30 2014
parent "Claude" <no no.no> writes:
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?
Dec 30 2014
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Dec 30 2014
parent "Claude" <no no.no> writes:
 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).
Jan 08 2015