digitalmars.D - Is there a cleaner way of doing this?
- Shachar Shemesh (38/38) Aug 07 2017 It is often desired to have a struct with an extra parameter. The common...
- =?UTF-8?Q?Ali_=c3=87ehreli?= (29/57) Aug 07 2017 A mixin template can work. The whole param-related code is in one place
- Timon Gehr (10/60) Aug 07 2017 struct S(T...) {
- Shachar Shemesh (7/18) Aug 07 2017 It's an interesting approach. It has the down side that it also accepts
- Timon Gehr (16/38) Aug 08 2017 I don't see why not, but you can just add a template constraint:
- Andrei Alexandrescu (2/45) Aug 08 2017 Very good creative use of the language, kudos Timon. -- Andrei
- Diego (12/52) Aug 07 2017 You can use type default initialization property:
- Dgame (21/61) Aug 07 2017 Why don't you use a factory method?
- Mark (21/44) Aug 12 2017 I was going to suggest using Algebraic/Variant, as in:
- Mark (3/5) Aug 12 2017 This should read:
It is often desired to have a struct with an extra parameter. The common
way to do this is like so:
struct S(T) {
T param;
void initialize(T param) {
this.param = param;
// Other stuff
}
}
The problem is what happens when the param is optional. The common way
to do this is to set T to void. This results in the following code:
struct S(T) {
enum HasParam = !is(T == void);
static if( HasParam ) {
T param;
}
static if( HasParam ) {
void initialize(T param) {
this.param = param;
// Other stuff
}
} else {
void initialize() {
// Same other stuff as above!
}
}
}
This is both tedious and error prone. Is there a cleaner way of doing this?
Just as an unrealistic fantasy, if the following code was legal, the
problem would be resolved on its own:
void func(void p) {
void param;
param = p;
return param;
}
Of course, that code has its own set of problems, and I'm not really
suggesting that change.
Shachar
Aug 07 2017
On 08/07/2017 01:01 AM, Shachar Shemesh wrote:
It is often desired to have a struct with an extra parameter. The common
way to do this is like so:
struct S(T) {
T param;
void initialize(T param) {
this.param = param;
// Other stuff
}
}
The problem is what happens when the param is optional. The common way
to do this is to set T to void. This results in the following code:
struct S(T) {
enum HasParam = !is(T == void);
static if( HasParam ) {
T param;
}
static if( HasParam ) {
void initialize(T param) {
this.param = param;
// Other stuff
}
} else {
void initialize() {
// Same other stuff as above!
}
}
}
This is both tedious and error prone. Is there a cleaner way of doing this?
A mixin template can work. The whole param-related code is in one place
and the void specialization obviates the need for static if:
mixin template ParamCode(T) {
T param;
void initializeParam(T param) {
this.param = param;
initialize();
}
}
template ParamCode(T : void) {
}
struct S(T) {
mixin ParamCode!T;
void initialize() {
// ...
}
}
unittest {
auto a = S!int();
static assert(a.sizeof == int.sizeof);
a.initializeParam(42);
auto b = S!void();
static assert(b.sizeof == 1);
b.initialize();
}
void main() {
}
Ali
Aug 07 2017
On 07.08.2017 10:01, Shachar Shemesh wrote:It is often desired to have a struct with an extra parameter. The common way to do this is like so: struct S(T) { T param; void initialize(T param) { this.param = param; // Other stuff } } The problem is what happens when the param is optional. The common way to do this is to set T to void. This results in the following code: struct S(T) { enum HasParam = !is(T == void); static if( HasParam ) { T param; } static if( HasParam ) { void initialize(T param) { this.param = param; // Other stuff } } else { void initialize() { // Same other stuff as above! } } } This is both tedious and error prone. Is there a cleaner way of doing this? ...struct S(T...) { T param; void initialize(T param) { this.param = param; // Other stuff } } Then, use S!() instead of S!void.Just as an unrealistic fantasy, if the following code was legal, the problem would be resolved on its own: void func(void p) { void param; param = p; return param; } Of course, that code has its own set of problems, and I'm not really suggesting that change. ShacharThe only reason this code is problematic is that void.sizeof == 1.
Aug 07 2017
On 07/08/17 12:37, Timon Gehr wrote:
struct S(T...) {
T param;
void initialize(T param) {
this.param = param;
// Other stuff
}
}
Then, use S!() instead of S!void.
It's an interesting approach. It has the down side that it also accepts
S!(int, string, int[23], double), and I'm still not sure what I think
about this option (i.e. - whether I want to allow it).
If not, then things start to look quite misleading to the user, and I'd
rather have the ugly static-ifs than do that.
Shachar
Aug 07 2017
On 08.08.2017 08:06, Shachar Shemesh wrote:On 07/08/17 12:37, Timon Gehr wrote:I don't see why not, but you can just add a template constraint: struct S(T...) if(T.length<=1) { ... } You can also hide the approach as an implementation detail: struct S(T){ static if(is(T==void)){ private alias X = AliasSeq!(); }else{ private alias X = AliasSeq!T; } X param; void initialize(X param){ this.param=param; // ... } }struct S(T...) { T param; void initialize(T param) { this.param = param; // Other stuff } } Then, use S!() instead of S!void.It's an interesting approach. It has the down side that it also accepts S!(int, string, int[23], double), and I'm still not sure what I think about this option (i.e. - whether I want to allow it). If not, then things start to look quite misleading to the user, and I'd rather have the ugly static-ifs than do that. Shachar
Aug 08 2017
On 08/08/2017 05:03 AM, Timon Gehr wrote:On 08.08.2017 08:06, Shachar Shemesh wrote:Very good creative use of the language, kudos Timon. -- AndreiOn 07/08/17 12:37, Timon Gehr wrote:I don't see why not, but you can just add a template constraint: struct S(T...) if(T.length<=1) { ... } You can also hide the approach as an implementation detail: struct S(T){ static if(is(T==void)){ private alias X = AliasSeq!(); }else{ private alias X = AliasSeq!T; } X param; void initialize(X param){ this.param=param; // ... } }struct S(T...) { T param; void initialize(T param) { this.param = param; // Other stuff } } Then, use S!() instead of S!void.It's an interesting approach. It has the down side that it also accepts S!(int, string, int[23], double), and I'm still not sure what I think about this option (i.e. - whether I want to allow it). If not, then things start to look quite misleading to the user, and I'd rather have the ugly static-ifs than do that. Shachar
Aug 08 2017
On Monday, 7 August 2017 at 08:01:26 UTC, Shachar Shemesh wrote:
It is often desired to have a struct with an extra parameter.
The common way to do this is like so:
struct S(T) {
T param;
void initialize(T param) {
this.param = param;
// Other stuff
}
}
The problem is what happens when the param is optional. The
common way to do this is to set T to void. This results in the
following code:
struct S(T) {
enum HasParam = !is(T == void);
static if( HasParam ) {
T param;
}
static if( HasParam ) {
void initialize(T param) {
this.param = param;
// Other stuff
}
} else {
void initialize() {
// Same other stuff as above!
}
}
}
This is both tedious and error prone. Is there a cleaner way of
doing this?
Just as an unrealistic fantasy, if the following code was
legal, the problem would be resolved on its own:
void func(void p) {
void param;
param = p;
return param;
}
Of course, that code has its own set of problems, and I'm not
really suggesting that change.
Shachar
You can use type default initialization property:
struct S(T) {
T param;
void initialize(T param = T.init) {
this.param = param;
// Other stuff
}
}
S!int s;
s.initialize(42); // works
s.initialize(); // also works; s.param == int.init == 0
Aug 07 2017
On Monday, 7 August 2017 at 08:01:26 UTC, Shachar Shemesh wrote:
It is often desired to have a struct with an extra parameter.
The common way to do this is like so:
struct S(T) {
T param;
void initialize(T param) {
this.param = param;
// Other stuff
}
}
The problem is what happens when the param is optional. The
common way to do this is to set T to void. This results in the
following code:
struct S(T) {
enum HasParam = !is(T == void);
static if( HasParam ) {
T param;
}
static if( HasParam ) {
void initialize(T param) {
this.param = param;
// Other stuff
}
} else {
void initialize() {
// Same other stuff as above!
}
}
}
This is both tedious and error prone. Is there a cleaner way of
doing this?
Just as an unrealistic fantasy, if the following code was
legal, the problem would be resolved on its own:
void func(void p) {
void param;
param = p;
return param;
}
Of course, that code has its own set of problems, and I'm not
really suggesting that change.
Shachar
Why don't you use a factory method?
struct S(T)
{
T p;
static make(T p)
{
S s;
s.p = p;
return s;
}
static make()
{
return S();
}
}
void main()
{
auto s1 = S!int.make;
auto s2 = S!string.make;
}
Aug 07 2017
On Monday, 7 August 2017 at 08:01:26 UTC, Shachar Shemesh wrote:
The problem is what happens when the param is optional. The
common way to do this is to set T to void. This results in the
following code:
struct S(T) {
enum HasParam = !is(T == void);
static if( HasParam ) {
T param;
}
static if( HasParam ) {
void initialize(T param) {
this.param = param;
// Other stuff
}
} else {
void initialize() {
// Same other stuff as above!
}
}
}
This is both tedious and error prone. Is there a cleaner way of
doing this?
Shachar
I was going to suggest using Algebraic/Variant, as in:
void initialize(Algebraic!(int,void)) {
static if(hasParam)
this.param = param;
// Other stuff
}
but unfortunately Algebraic seems very cumbersome to use. You
can't call initialize with an int (or "parameterlessly"); you
have to use it like this:
x.initialize(Algebraic!(int,void)(my_integer)); //
which is bad in many ways, e.g. you'll have to import std.variant
whenver you want to call initialize.
Ideally, I would have liked to write something like this:
void initialize( static if(hasParam) { mixin("T param"); } ) {
static if(hasParam) {
this.param = param;
}
// Other stuff
}
but of course this is currently not possible.
Aug 12 2017
On Saturday, 12 August 2017 at 15:02:34 UTC, Mark wrote:
I was going to suggest using Algebraic/Variant, as in:
void initialize(Algebraic!(int,void)) {
This should read:
void initialize(Algebraic!(int,void) param) {
Aug 12 2017









=?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> 