Thread overview
Unqual fails with pointer?
Jun 13, 2013
Namespace
Jun 13, 2013
Namespace
Jun 13, 2013
Namespace
Jun 13, 2013
bearophile
Jun 14, 2013
Namespace
June 13, 2013
----
import std.traits : Unqual;

void main() {
	static assert(is(Unqual!int == int));
	static assert(is(Unqual!(const int) == int));
	static assert(is(Unqual!(immutable int) == int));
	static assert(is(Unqual!(shared int) == int));
	static assert(is(Unqual!(shared(const int)) == int));
	static assert(is(Unqual!int* == int*));
	static assert(is(Unqual!(const int*) == int*)); /// Error: static assert  (is(const(int)* == int*)) is false
}
----

Is this expected?
June 13, 2013
On Thursday, 13 June 2013 at 21:32:19 UTC, Namespace wrote:
> ----
> import std.traits : Unqual;
>
> void main() {
> 	static assert(is(Unqual!int == int));
> 	static assert(is(Unqual!(const int) == int));
> 	static assert(is(Unqual!(immutable int) == int));
> 	static assert(is(Unqual!(shared int) == int));
> 	static assert(is(Unqual!(shared(const int)) == int));
> 	static assert(is(Unqual!int* == int*));
> 	static assert(is(Unqual!(const int*) == int*)); /// Error: static assert  (is(const(int)* == int*)) is false
> }
> ----
>
> Is this expected?

This works:
----
template UnqualPtr(T) {
	static if (is(T == shared(const U*), U))
		alias UnqualPtr = U*;
	else static if (is(T == const U*, U))
		alias UnqualPtr = U*;
	else static if (is(T == immutable U*, U))
		alias UnqualPtr = U*;
	else static if (is(T == inout U*, U))
		alias UnqualPtr = U*;
	else static if (is(T == shared U*, U))
		alias UnqualPtr = U*;
	else static if (is(T == shared(const U), U))
		alias UnqualPtr = U;
	else static if (is(T == const U, U))
		alias UnqualPtr = U;
	else static if (is(T == immutable U, U))
		alias UnqualPtr = U;
	else static if (is(T == inout U, U))
		alias UnqualPtr = U;
	else static if (is(T == shared U, U))
		alias UnqualPtr = U;
	else
		alias UnqualPtr = T;
}
----
June 13, 2013
Just out of interest: how safe is something like this:

----
UnqualPtr!From unqual_cast(From : U*, U)(From from) {
	union Cast {
		From from;
		UnqualPtr!From to;
	}
	
	Cast c;
	c.from = from;
	
	return c.to;
}

const B* cb = ...;
B* b = unqual_cast(cb);
----

compared to this:

----
const B* cb = ...;
B* b = cast(B*) cb;
----

I'm just playing around in favor of something like 'const_cast' from C++.
June 13, 2013
Namespace:

> Just out of interest: how safe is something like this:
>
> ----
> UnqualPtr!From unqual_cast(From : U*, U)(From from) {
> 	union Cast {
> 		From from;
> 		UnqualPtr!From to;
> 	}
> 	
> 	Cast c;
> 	c.from = from;
> 	
> 	return c.to;
> }
>
> const B* cb = ...;
> B* b = unqual_cast(cb);
> ----
>
> compared to this:
>
> ----
> const B* cb = ...;
> B* b = cast(B*) cb;
> ----

Both are quite unsafe. As you know modifying const data in D causes bugs. The second is more bug-prone because you have to state the type again, so it's not DRY.

Bye,
bearophile
June 14, 2013
Thank you.