Jump to page: 1 2
Thread overview
Why code failed to compile for foo2?
Dec 11, 2021
apz28
Dec 11, 2021
Adam Ruppe
Dec 11, 2021
Stanislav Blinov
Dec 11, 2021
Adam Ruppe
Dec 12, 2021
Stanislav Blinov
Dec 12, 2021
apz28
Dec 13, 2021
Tejas
Dec 14, 2021
Tejas
Dec 14, 2021
apz28
Dec 15, 2021
Tejas
Dec 15, 2021
Tejas
Dec 13, 2021
apz28
December 11, 2021

void foo1(ubyte x) {}
void foo1(ushort x) {}
void foo1(uint x) {}
void foo1(ulong x) {}

import std.traits : isUnsigned, Unqual;
void foo2(T)(Unqual!T x) if(isUnsigned!T) {}

void main()
{
    import std.math;

    int s = 1;
    foo1(abs(s));
    foo2(abs(s)); //failed?
}

/*
onlineapp.d(15): Error: template onlineapp.foo2 cannot deduce function from argument types !()(int)
onlineapp.d(7): Candidate is: foo2(T)(Unqual!T x)
*/

December 11, 2021

On Saturday, 11 December 2021 at 22:50:45 UTC, apz28 wrote:

>

void foo2(T)(Unqual!T x) if(isUnsigned!T) {}

This means it treats foo2 as if it doesn't exist unless T is unsigned...

>

onlineapp.d(15): Error: template onlineapp.foo2 cannot deduce function from argument types !()(int)
onlineapp.d(7): Candidate is: foo2(T)(Unqual!T x)
*/

And this is telling you it had a signed value - int - which means it doesn't match.

For the other ones, the functions still exist, so it does whatever conversion it needs. Whereas with the template that constraint means the compiler acts like it doesn't exist at all and thus doesn't even attempt an automatic conversion.

December 11, 2021

On Saturday, 11 December 2021 at 22:59:52 UTC, Adam Ruppe wrote:

>

On Saturday, 11 December 2021 at 22:50:45 UTC, apz28 wrote:

>

void foo2(T)(Unqual!T x) if(isUnsigned!T) {}

This means it treats foo2 as if it doesn't exist unless T is unsigned...

>

onlineapp.d(15): Error: template onlineapp.foo2 cannot deduce function from argument types !()(int)
onlineapp.d(7): Candidate is: foo2(T)(Unqual!T x)
*/

And this is telling you it had a signed value - int - which means it doesn't match.

For the other ones, the functions still exist, so it does whatever conversion it needs. Whereas with the template that constraint means the compiler acts like it doesn't exist at all and thus doesn't even attempt an automatic conversion.

? No. If it was unsatisfied constraint, the error would've shown that. What's going on here is that the argument being passed is an int, when the parameter is an Unqual!T. So, https://dlang.org/spec/template.html#ifti would fail because there is no way of figuring out a T from an Unqual!T. Hence the message: cannot deduce function.

December 11, 2021

On Saturday, 11 December 2021 at 23:17:17 UTC, Stanislav Blinov wrote:

>

? No. If it was unsatisfied constraint, the error would've shown that.

And if you try to instantiate it, you'll see it is an unsatisfied constraint anyway. There's two layers of failure here.

Using Unqual there is pretty iffy, i wouldn't bother with it at all, but if you do anything, instead qualify it const.

But either way, then the constraint still fails since int isn't unsigned.

I'd really recommend simplifying this a lot.

December 12, 2021

On Saturday, 11 December 2021 at 23:44:59 UTC, Adam Ruppe wrote:

>

On Saturday, 11 December 2021 at 23:17:17 UTC, Stanislav Blinov wrote:

>

? No. If it was unsatisfied constraint, the error would've shown that.

And if you try to instantiate it, you'll see it is an unsatisfied constraint anyway. There's two layers of failure here.

Using Unqual there is pretty iffy, i wouldn't bother with it at all, but if you do anything, instead qualify it const.

But either way, then the constraint still fails since int isn't unsigned.

I'd really recommend simplifying this a lot.

??? There is no unsatisfied constraint, it doesn't get there :)

>

unq.d(6): Error: template unq.foo2 cannot deduce function from argument types !()(int)
unq.d(2): Candidate is: foo2(T)(Unqual!T x)

...because passed argument - int - becomes Unqual!T, making T unknown - template arg list is empty. Deduction fails :) If int is an Unqual!T, what is T? The constraint is testing T.

Now, if you explicitly instantiate - sure, you'd get unsatisfied constraint. But the OP seems to want IFTI, which simply can't work here.

@apz28, I can't figure out the intent here. To convert result of abs to an unsigned?

December 12, 2021

On Sunday, 12 December 2021 at 00:02:25 UTC, Stanislav Blinov wrote:

>

@apz28, I can't figure out the intent here. To convert result of abs to an unsigned?

The function logic works only for unsigned type and the parameter value can be altered in body hence Unqual. If not Unqual, must declare a local var and make a copy. Just asking if this can be done to avoid a cast by caller

December 13, 2021

On Sunday, 12 December 2021 at 03:02:28 UTC, apz28 wrote:

>

On Sunday, 12 December 2021 at 00:02:25 UTC, Stanislav Blinov wrote:

>

@apz28, I can't figure out the intent here. To convert result of abs to an unsigned?

The function logic works only for unsigned type and the parameter value can be altered in body hence Unqual. If not Unqual, must declare a local var and make a copy. Just asking if this can be done to avoid a cast by caller

AFAIK stuff like const int implicitly converts to int since int is passed by value so the constness of the original value is not violated.

That's why code like:

void main(){
	const int a = 55;
	int b = a;
}

compiles and executes.

So, in a similar vein, your code will transform to:

void foo1(ubyte x) {}
void foo1(ushort x) {}
void foo1(uint x) {}
void foo1(ulong x) {}

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
	foo3(x);
}


void foo3(ulong param){ //I'm assuming this is your function that you will pass your uint to
	writeln(param);
}

void main()
{
    import std.math;

    int s = int.min + 1; //abs returns int.min for abs(int.min) lol XD
    foo1(abs(s));
    foo2(abs(s)); //failed? //Not anymore :D
}

Again, please remember that std.math.algebraic:abs doesn't return uint for int and so on, please see the documentation:

>

Returns:

>

The absolute value of the number. If floating-point or integral, the return type will be the same as the input.

>

Limitations

>

Does not work correctly for signed intergal types and value Num.min.

December 13, 2021

On 12/11/21 10:02 PM, apz28 wrote:

>

On Sunday, 12 December 2021 at 00:02:25 UTC, Stanislav Blinov wrote:

>

@apz28, I can't figure out the intent here. To convert result of abs to an unsigned?

The function logic works only for unsigned type and the parameter value can be altered in body hence Unqual. If not Unqual, must declare a local var and make a copy. Just asking if this can be done to avoid a cast by caller

To translate a bit here, what apz28 is looking for is, given ANY value type that implicitly converts from the qualified value to the unqualified value, generate one function that only accepts the unqualified value.

You can wrap like:

void foo2(T)(T v) if (!is(Unqual!T == T))
{
   foo(Unqual!T(t));
}

This will inline as if you called it directly (which should just whittle down to a direct call to the correct foo2).

But D isn't currently smart enough to see through aliases, so IFTI will not work for what you are doing, even in a case like:

template foo2(T) if (!isUnqual!T == T)
{
   alias foo2 = .foo2!(Unqual!T);
}

It would be nice if IFTI gave some hooks between the parameter and the deduction, but it currently doesn't.

-Steve

December 13, 2021

On Saturday, 11 December 2021 at 23:44:59 UTC, Adam Ruppe wrote:

>

On Saturday, 11 December 2021 at 23:17:17 UTC, Stanislav Blinov wrote:

>

? No. If it was unsatisfied constraint, the error would've shown that.

And if you try to instantiate it, you'll see it is an unsatisfied constraint anyway. There's two layers of failure here.

Using Unqual there is pretty iffy, i wouldn't bother with it at all, but if you do anything, instead qualify it const.

But either way, then the constraint still fails since int isn't unsigned.

I'd really recommend simplifying this a lot.

  1. This is why there is a diverse logic for language rule vs template rule.
    The overload functions enjoy all benefits of implicit conversion rule but none for template

  2. This is why template implementation create more function bloats more than it needs to be as compilable example below

    import std.traits : isUnsigned, Unqual;
    void foo2(T, alias UT1 = Unqual!T)(T x)
    // You can create alias UT1 but not able to use it in function parameter
    if(isUnsigned!T)
    {
    alias UT2 = Unqual!T;
    pragma(msg, T.stringof);
    pragma(msg, UT1.stringof);
    pragma(msg, UT2.stringof);
    }

    void main()
    {
    import std.math;

     int s = 1;
     foo2(cast(uint)abs(s));
     foo2(cast(const(uint))abs(s));
    

    }

Output as below
uint
uint
uint
const(uint)
uint
uint

December 14, 2021

On Monday, 13 December 2021 at 20:43:51 UTC, Steven Schveighoffer wrote:

>

On 12/11/21 10:02 PM, apz28 wrote:

>

On Sunday, 12 December 2021 at 00:02:25 UTC, Stanislav Blinov wrote:

>

@apz28, I can't figure out the intent here. To convert result of abs to an unsigned?

The function logic works only for unsigned type and the parameter value can be altered in body hence Unqual. If not Unqual, must declare a local var and make a copy. Just asking if this can be done to avoid a cast by caller

To translate a bit here, what apz28 is looking for is, given ANY value type that implicitly converts from the qualified value to the unqualified value, generate one function that only accepts the unqualified value.

You can wrap like:

void foo2(T)(T v) if (!is(Unqual!T == T))
{
   foo(Unqual!T(t));
}

This will inline as if you called it directly (which should just whittle down to a direct call to the correct foo2).

But D isn't currently smart enough to see through aliases, so IFTI will not work for what you are doing, even in a case like:

template foo2(T) if (!isUnqual!T == T)
{
   alias foo2 = .foo2!(Unqual!T);
}

It would be nice if IFTI gave some hooks between the parameter and the deduction, but it currently doesn't.

-Steve

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?

« First   ‹ Prev
1 2