const confusion

Witold Baryluk baryluk at smp.if.uj.edu.pl
Tue Jun 23 06:41:52 PDT 2009


Dnia 2009-06-01, pon o godzinie 16:44 -0400, Steven Schveighoffer pisze:
> On Mon, 01 Jun 2009 16:01:04 -0400, Witold Baryluk  
> <baryluk at smp.if.uj.edu.pl> wrote:
> 
> > Dnia 2009-05-31, nie o godzinie 15:36 -0400, Jarrett Billingsley pisze:
> >> On Sun, May 31, 2009 at 3:26 PM, Witold Baryluk
> >> <baryluk at smp.if.uj.edu.pl> wrote:
> >> >
> >> > Horrible.
> >> >
> >> > How to ensure constness of data, and still have possibility of  
> >> changing references of local variables?
> >>
> >> Rebindable.
> >>
> >> http://www.digitalmars.com/d/2.0/phobos/std_typecons.html#Rebindable
> >
> > Thanks. I was already thinking about implementing something like this.
> > It is very thin, and probably doesn't eat even single byte more than
> > original reference.
> >
> > So generally we need to cheat: union with const and non-const version +
> > opAssign/opDot, and some hidden casts. If everybody is doing this, why
> > not.
> >
> > Only one problem is that i need to make some wrappers for it:
> >
> > alias Rebindable!(C) CC;
> >
> >
> > first try:
> >
> > auto c1 = CC(new C(1));
> > auto c2 = CC(new C(2, c1)); // oops doesn't work
> > c2 = c2.b();
> >
> > second try:
> >
> > auto c1 = CC(new C(1));
> > auto c2 = CC(new C(2, c1.opDot())); // ok, works
> > c2 = c2.b();
> >
> >
> > define some function on original data:
> >
> > int something(in C c) {
> > 	return c.a;
> > }
> >
> > something(c2); // oops, doesn't work
> >
> > something(c2.opDot()); // ok, works
> >
> >
> >
> > So generally now i need to overload all my functions to support also
> > Rebindable!(C), where I will unwrap object and call original function?
> > The same with constructors.
> >
> > Can't be this done more simpler?
> >
> > As I remember there was something like opCast (for explicit casts)?
> > Maybe Rebindable should have it casting to original type (with const)?
> >
> 
> You are running into limitations that are planned to be fixed.
> 
> For example, rebindable probably shouldn't use opDot anymore...  it should  
> use alias this.
> 
> With opDot, you don't have implicit casting back to the original type.   
> But alias this provides that, not sure if aliasing a union member has been  
> tested...
> 
> Also, I believe Rebindable!(const C) is what you really want (I've argued  
> in the past that Rebindable should just assume that it's type should be  
> const).  Rebindable!(T) is just an alias to T if T is not const, which is  
> IMO absolutely useless.
> 
> Another thing I just noticed, which probably should be fixed, there is an  
> alias for get which gets the original item.  get's a pretty common member  
> name, I don't think it should be overridden by Rebindable.
> 
> In fact, I think rebindable needs almost a rewrite with the recent  
> developments of D2.
> 
> The goal of Rebindable is to transparently implement the sort of  
> "tail-const" behavior you want without any of the pain you are currently  
> experiencing.  If it doesn't work seamlessly (except for where you wish to  
> explicitly define "this is a rebindable reference"), then it's not  
> finished.
> 
> Andrei?
> 
I have curently something like this in my implementation of rebindable.

//alias Rebindable!(const C) CC;
// todo: opAssign(Rebindable!(T)) is missing so c4 = c3
// todo: T opCast() is missing for explicit cast(T)

// todo: opdot needs const

// because of this here is own Rebindable

template RBMixin(T, RetT) {
static if (is(T X == const(U), U) || is(T X == invariant(U), U)) {
	private union {
		T original;
		U stripped;
	}

	RetT opAssign(T another) {
		stripped = cast(U)another;
		return this;
	}

	RetT opAssign(RetT another) {
		stripped = another.stripped;
		return this;
	}

	static RetT opCall(T initializer) {
		//return RetT(initializer);
		RetT result;
		result = initializer;
		return result;
	}

	T opDot() const {
		return original;
	}

	static if (!is(T.opCast)) {
	T opCast() {
		return original;
	}
	}
}
}

template RB(T) {
	static if (!is(T X == const(U), U) && !is(T X == invariant(U), U)) {
		alias T RB;
	} else {
		struct RB {
			mixin RBMixin!(T, RB);
			alias original get; // legacy get
		}
	}
}




Then i can just use RB!(const!(mytype)), or mixin it into own struct.

I think i will rewrite it to use "alias this", and remove some
other limitation


What you think?

> -Steve




More information about the Digitalmars-d-learn mailing list