December 14, 2021

On Tuesday, 14 December 2021 at 05:04:46 UTC, Tejas wrote:

>

Is there anything wrong with the answer I posted?

Can you please tell me if there's anything dissatisfactory about it? I feel like it does everything the OP wants.

Also, am I wrong in using Unconst over Unqual? Isn't Unqual overkill if you just want to cast away const?

  1. A template function should behave as to replace 4 overload functions
    There is special logic for parameter type (2 vs 4...)

  2. Your implementation does not remove 'const' as below
    import std.traits : Unconst;
    import std.stdio : writeln;

    void foo2(T)(T x) if(is(Unconst!(T) : ulong)) {//You don't need Unqual for this
    pragma(msg, T.stringof);
    writeln(x);
    }

    void main()
    {
    import std.math;

     const int s1 = -3;
     int s2 = -2;
     foo2(abs(s1));
     foo2(abs(s2));
    
     enum byte b1 = 0;
     const byte b2;
     byte b3;
     foo2(b1);
     foo2(b2);
     foo2(b3);
    

    }
    --Output
    const(int)
    int
    byte
    const(byte)
    3
    2
    0
    0
    0

December 14, 2021

On 12/14/21 12:04 AM, Tejas wrote:

>

Is there anything wrong with the answer I posted?

Can you please tell me if there's anything dissatisfactory about it? I feel like it does everything the OP wants.

Also, am I wrong in using Unconst over Unqual? Isn't Unqual overkill if you just want to cast away const?

Unqual is fine for value types, it should work in all cases.

The OP's problem is that it's entirely possible to build an overload set with just the unqualified types specified (in this case, an integral type), but there's not a way to express that and still have it work with IFTI.

In other words, if you have a call like:

const int x;
foo2(x);

You want to have the parameter be mutable inside foo2. There currently isn't a way to express that if foo2 is an IFTI template. The opposite is actually easily expressable:

void foo2(T)(const(T) val)
{
   // only one instantiation of foo2 per const(int), immutable(int), int,
   // and now val is const, even if the argument is not
}

With a standard function it works just fine due to implicit conversion, but with IFTI, there's no way to express it because it goes through an alias. The closest you can come is to write a wrapper shim that calls the right instantiation. This should be OK as long as inlining is happening, but it seems like extra work for the optimizer, when it should be easy to express in the language somehow.

BTW, there is a related issue: https://issues.dlang.org/show_bug.cgi?id=1807

-Steve

December 15, 2021

On Tuesday, 14 December 2021 at 13:25:04 UTC, apz28 wrote:

>

On Tuesday, 14 December 2021 at 05:04:46 UTC, Tejas wrote:

>

Is there anything wrong with the answer I posted?

Can you please tell me if there's anything dissatisfactory about it? I feel like it does everything the OP wants.

Also, am I wrong in using Unconst over Unqual? Isn't Unqual overkill if you just want to cast away const?

  1. A template function should behave as to replace 4 overload functions
    There is special logic for parameter type (2 vs 4...)

  2. Your implementation does not remove 'const' as below
    import std.traits : Unconst;
    import std.stdio : writeln;

    void foo2(T)(T x) if(is(Unconst!(T) : ulong)) {//You don't need Unqual for this
    pragma(msg, T.stringof);
    writeln(x);
    }

    void main()
    {
    import std.math;

     const int s1 = -3;
     int s2 = -2;
     foo2(abs(s1));
     foo2(abs(s2));
    
     enum byte b1 = 0;
     const byte b2;
     byte b3;
     foo2(b1);
     foo2(b2);
     foo2(b3);
    

    }
    --Output
    const(int)
    int
    byte
    const(byte)
    3
    2
    0
    0
    0

Then I suggest using inout, if you're trying to reduce number of template instantiations

import std.traits : Unconst;
import std.stdio : writeln;

void foo2(T)(inout(T) x) if(is(Unconst!(T) : ulong)) {//You don't need Unqual for this
	pragma(msg, T.stringof);
	writeln(x);
}

void main(){
	import std.math;
	const int ci = -3;
	int i = -2;
	immutable int ii = 24342;
	foo2(abs(ci));
	foo2(abs(i));
	foo2(ii);
	
	byte b = 0;
	const byte cb;
	immutable byte ib;
	foo2(b);
	foo2(cb);
	foo2(ib);
	
	const long cl = 4554;
	long l = 12313;
	immutable long il = 3242343;
	foo2(cl);
	foo2(l);
	foo2(il);
	
}

Output(Compile-time):
int
byte
long

Output(Runtime):
3
2
24342

0
0
0

4554
12313
3242343
December 15, 2021

On Tuesday, 14 December 2021 at 15:14:40 UTC, Steven Schveighoffer wrote:

>

On 12/14/21 12:04 AM, Tejas wrote:

>

Is there anything wrong with the answer I posted?

Can you please tell me if there's anything dissatisfactory about it? I feel like it does everything the OP wants.

Also, am I wrong in using Unconst over Unqual? Isn't Unqual overkill if you just want to cast away const?

Unqual is fine for value types, it should work in all cases.

The OP's problem is that it's entirely possible to build an overload set with just the unqualified types specified (in this case, an integral type), but there's not a way to express that and still have it work with IFTI.

In other words, if you have a call like:

const int x;
foo2(x);

You want to have the parameter be mutable inside foo2. There currently isn't a way to express that if foo2 is an IFTI template. The opposite is actually easily expressable:

void foo2(T)(const(T) val)
{
   // only one instantiation of foo2 per const(int), immutable(int), int,
   // and now val is const, even if the argument is not
}

With a standard function it works just fine due to implicit conversion, but with IFTI, there's no way to express it because it goes through an alias. The closest you can come is to write a wrapper shim that calls the right instantiation. This should be OK as long as inlining is happening, but it seems like extra work for the optimizer, when it should be easy to express in the language somehow.

BTW, there is a related issue: https://issues.dlang.org/show_bug.cgi?id=1807

-Steve

Yeah, now I understand he's trying to reduce number of instantiations.

In that case, I'd use inout, but it'd be the same as your case : can't modify the argument anymore.

But we can pass that to another function that accepts ulong (as that seems to be the OP's usecase anyways), which can then modify it :D

import std.traits : Unconst;
import std.stdio : writeln;

void foo2(T)(inout(T) x) if(is(Unconst!(T) : ulong)) {//You don't need Unqual for this
	pragma(msg, T.stringof);
	foo3(x);
}

void foo3(ulong param){
	writeln(param, " before");
	param +=10;	
	writeln(param, " after"); // can also modify params now
}
void main(){
	import std.math;
	const int ci = -3;
	int i = -2;
	immutable int ii = 24342;
	foo2(abs(ci));
	foo2(abs(i));
	foo2(ii);
	
	byte b = 0;
	const byte cb;
	immutable byte ib;
	foo2(b);
	foo2(cb);
	foo2(ib);
	
	const long cl = 4554;
	long l = 12313;
	immutable long il = 3242343;
	foo2(cl);
	foo2(l);
	foo2(il);
	
}
1 2
Next ›   Last »