www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Class parameters that are either setable at run-time or compile-time

reply "Markus Mayr" <markus.mayr outlook.com> writes:
Hello,

I am new to D. I am sorry if this question was already answered 
or if it is trivial. I am having a class. That class takes 
several parameters that may be known at either compile time or 
run time. I want users of my class to be able to pass the 
parameters either as template parameters to the class or to the 
constructor of that class. At the moment, I have got the 
following code:

     class X(int a = some_dummy_value, int b = some_dummy_value)
     {
         static if (a == some_dummy_value) static immutable int a_ 
= a;
         else immutable int a_;

         // etc.

         this(int a = some_dummy_value, int b = some_dummy_value) {
             static if (a != some_dummy_value) this.a_ = a;
             static if (b != some_dummy_value) this.b_ = b;
         }
     };

This works, as far as I can tell. But there is one problem: users 
may forget to provide the value at compile time and run time. In 
that case, the members a_, b_ end up with some_dummy_values. Of 
course, I can notify the user at run time about this 
misbehaviour, but I would prefer to tell them at compile time.

The only solution I am aware of is to use static if in order to 
provide one of four constructors depending on the compile time 
values of a, b, i.e.
* none provided at compile time,
* a provided at compile time,
* b provided at compile time,
* both provided at compile time.

This is perfectly fine for one or two arguments, but I have 
gotten three of them (i.e. 8 constructors) and may want to add 
more later on. Since the number of constructors scales 
exponentially with the number of parameters, I have a feeling 
that this approach won't scale well.

Is there any elegant solution to the problem?

By the way, this is why I am doing this: Depending on the values 
of a and b, the class chooses how to implement some parts of its 
interface; if a or b are not provided, it may choose generic but 
slow fall back implementations. If there is any other solution to 
that problem, I also would like to know.

Thanks a lot and I hope this is how this mailing list works!

Best regards,
Markus Mayr
Aug 10 2014
next sibling parent Rikki Cattermole <alphaglosined gmail.com> writes:
On 10/08/2014 10:47 p.m., Markus Mayr wrote:
 Hello,

 I am new to D. I am sorry if this question was already answered or if it
 is trivial. I am having a class. That class takes several parameters
 that may be known at either compile time or run time. I want users of my
 class to be able to pass the parameters either as template parameters to
 the class or to the constructor of that class. At the moment, I have got
 the following code:

      class X(int a = some_dummy_value, int b = some_dummy_value)
      {
          static if (a == some_dummy_value) static immutable int a_ = a;
          else immutable int a_;

          // etc.

          this(int a = some_dummy_value, int b = some_dummy_value) {
              static if (a != some_dummy_value) this.a_ = a;
              static if (b != some_dummy_value) this.b_ = b;
          }
      };

 This works, as far as I can tell. But there is one problem: users may
 forget to provide the value at compile time and run time. In that case,
 the members a_, b_ end up with some_dummy_values. Of course, I can
 notify the user at run time about this misbehaviour, but I would prefer
 to tell them at compile time.

 The only solution I am aware of is to use static if in order to provide
 one of four constructors depending on the compile time values of a, b, i.e.
 * none provided at compile time,
 * a provided at compile time,
 * b provided at compile time,
 * both provided at compile time.

 This is perfectly fine for one or two arguments, but I have gotten three
 of them (i.e. 8 constructors) and may want to add more later on. Since
 the number of constructors scales exponentially with the number of
 parameters, I have a feeling that this approach won't scale well.

 Is there any elegant solution to the problem?

 By the way, this is why I am doing this: Depending on the values of a
 and b, the class chooses how to implement some parts of its interface;
 if a or b are not provided, it may choose generic but slow fall back
 implementations. If there is any other solution to that problem, I also
 would like to know.

 Thanks a lot and I hope this is how this mailing list works!

 Best regards,
 Markus Mayr
Unless you need to change the defaults of the values being passed in, don't pass them by template parameters. Please please please use constructors. They work at both compile time and runtime. Remember every change in template parameters equals a new type. http://dlang.org/class.html#constructors
Aug 10 2014
prev sibling parent "Martijn Pot" <martijnpot52 gmail.com> writes:
On Sunday, 10 August 2014 at 10:47:34 UTC, Markus Mayr wrote:
 Hello,

 I am new to D. I am sorry if this question was already answered 
 or if it is trivial. I am having a class. That class takes 
 several parameters that may be known at either compile time or 
 run time. I want users of my class to be able to pass the 
 parameters either as template parameters to the class or to the 
 constructor of that class. At the moment, I have got the 
 following code:

     class X(int a = some_dummy_value, int b = some_dummy_value)
     {
         static if (a == some_dummy_value) static immutable int 
 a_ = a;
         else immutable int a_;

         // etc.

         this(int a = some_dummy_value, int b = 
 some_dummy_value) {
             static if (a != some_dummy_value) this.a_ = a;
             static if (b != some_dummy_value) this.b_ = b;
         }
     };

 This works, as far as I can tell. But there is one problem: 
 users may forget to provide the value at compile time and run 
 time. In that case, the members a_, b_ end up with 
 some_dummy_values. Of course, I can notify the user at run time 
 about this misbehaviour, but I would prefer to tell them at 
 compile time.

 The only solution I am aware of is to use static if in order to 
 provide one of four constructors depending on the compile time 
 values of a, b, i.e.
 * none provided at compile time,
 * a provided at compile time,
 * b provided at compile time,
 * both provided at compile time.

 This is perfectly fine for one or two arguments, but I have 
 gotten three of them (i.e. 8 constructors) and may want to add 
 more later on. Since the number of constructors scales 
 exponentially with the number of parameters, I have a feeling 
 that this approach won't scale well.

 Is there any elegant solution to the problem?

 By the way, this is why I am doing this: Depending on the 
 values of a and b, the class chooses how to implement some 
 parts of its interface; if a or b are not provided, it may 
 choose generic but slow fall back implementations. If there is 
 any other solution to that problem, I also would like to know.

 Thanks a lot and I hope this is how this mailing list works!

 Best regards,
 Markus Mayr
A couple of words (search terms) pop up in my mind: 1) inversion of control / Dependency injection. The class has a member which does the actual work. This member is a reference to an object passed in e.g. the constructor. 2) Factory pattern A Factory determines how the object are created. Don't let the objects do that themselves. This breaks the single responsibility 'rule'. Note that a Factory works nice together with 1). 3) Inheritance. You could create multiple classes which override certain functions. This also works with 1) and 2)
Aug 10 2014