Thread overview
Function hijack on selective import
Dec 26, 2017
rumbu
Dec 26, 2017
Adam D. Ruppe
Dec 26, 2017
rumbu
Dec 26, 2017
Adam D. Ruppe
Dec 27, 2017
rumbu
Jan 16, 2018
rumbu
Jan 16, 2018
H. S. Teoh
Jan 16, 2018
rumbu
December 26, 2017
Is there anyway to extend an existing function to accept custom data types?



****************
Option 1 - global import of std.math


import std.math;

struct Custom {}

int signbit(T)(T x) if (is(T == Custom))
{
    return 0;
}

Custom c;
assert(signbit(c) == 0);
assert(signbit(-1.0) == 1);

Error: template main.signbit cannot deduce function from argument types !()(double), candidates are:
main.signbit(T)(T x) if (is(T == Custom))


*******************
Option 2 - selective import of std.math

import std.math : signbit;

struct Custom {}

int signbit(T)(T x) if (is(T == Custom))
{
    return 0;
}

Custom c;
assert(signbit(c) == 0);
assert(signbit(-1.0) == 1);


main.signbit called with argument types (Custom) matches both:
\..\src\phobos\std\math.d(5721):     std.math.signbit!(Custom).signbit(Custom x)
and:
main.signbit!(Custom).signbit(Custom x)
December 26, 2017
The mistake you're making is using a constraint when you should try a specialization:


int signbit(T:Custom)(T x)
{
    return 0;
}


That means to use this specialized function when T is Custom. Now, you just need to merge the overload sets:

import std.math;
alias signbit = std.math.signbit; // this merges local signbit with std.math.signbit


and boom it should compile and call your version.

December 26, 2017
On Tuesday, 26 December 2017 at 16:15:55 UTC, Adam D. Ruppe wrote:
> The mistake you're making is using a constraint when you should try a specialization:
>
>
> int signbit(T:Custom)(T x)
> {
>     return 0;
> }
>
>
> That means to use this specialized function when T is Custom. Now, you just need to merge the overload sets:
>
> import std.math;
> alias signbit = std.math.signbit; // this merges local signbit with std.math.signbit
>
>
> and boom it should compile and call your version.

"Custom" is a templated struct. I cannot imagine all the instantiations of Custom to write template specialisations for each of them.

My opinion is that the mistake is in std.math, because std.math.signbit accepts any type instead to be constrained to float types. Actually, calling std.math.signbit with any other type than float will result in compiler error because signbit expects some float traits for the provided type:

int signbit(X)(X x) @nogc @trusted pure nothrow
{
    alias F = floatTraits!(X);
    return ((cast(ubyte *)&x)[F.SIGNPOS_BYTE] & 0x80) != 0;
}


December 26, 2017
On Tuesday, 26 December 2017 at 19:41:47 UTC, rumbu wrote:
> "Custom" is a templated struct. I cannot imagine all the instantiations of Custom to write template specialisations for each of them.

You can specialize on templated structs generically.

int foo(T : Bar!(X, Y), X, Y)

that kind of thing covers any case of Bar!(X,y)
December 27, 2017
On Tuesday, 26 December 2017 at 20:21:11 UTC, Adam D. Ruppe wrote:
> On Tuesday, 26 December 2017 at 19:41:47 UTC, rumbu wrote:
>> "Custom" is a templated struct. I cannot imagine all the instantiations of Custom to write template specialisations for each of them.
>
> You can specialize on templated structs generically.
>
> int foo(T : Bar!(X, Y), X, Y)
>
> that kind of thing covers any case of Bar!(X,y)

Thank you, Adam.
January 16, 2018
On Tuesday, 26 December 2017 at 20:21:11 UTC, Adam D. Ruppe wrote:
> On Tuesday, 26 December 2017 at 19:41:47 UTC, rumbu wrote:
>> "Custom" is a templated struct. I cannot imagine all the instantiations of Custom to write template specialisations for each of them.
>
> You can specialize on templated structs generically.
>
> int foo(T : Bar!(X, Y), X, Y)
>
> that kind of thing covers any case of Bar!(X,y)

Even specialized, now I have another problem:

std.math:

int signbit(X)(X x) { ... }

mylibrary:

int signbit(D: Decimal!bits, int bits) { ... }

=============

end user:

import std.math;
import mylibrary;

Decimal!32 d;
float f;

auto y = signbit(f); //ok, call to std.math.signbit
auto x = signbit(d); //error, also calls std.math.signbit

January 16, 2018
On Tue, Jan 16, 2018 at 07:14:00PM +0000, rumbu via Digitalmars-d-learn wrote:
> On Tuesday, 26 December 2017 at 20:21:11 UTC, Adam D. Ruppe wrote:
> > On Tuesday, 26 December 2017 at 19:41:47 UTC, rumbu wrote:
> > > "Custom" is a templated struct. I cannot imagine all the instantiations of Custom to write template specialisations for each of them.
> > 
> > You can specialize on templated structs generically.
> > 
> > int foo(T : Bar!(X, Y), X, Y)
> > 
> > that kind of thing covers any case of Bar!(X,y)
> 
> Even specialized, now I have another problem:
> 
> std.math:
> 
> int signbit(X)(X x) { ... }
> 
> mylibrary:
> 
> int signbit(D: Decimal!bits, int bits) { ... }
> 
> =============
> 
> end user:
> 
> import std.math;
> import mylibrary;
> 
> Decimal!32 d;
> float f;
> 
> auto y = signbit(f); //ok, call to std.math.signbit
> auto x = signbit(d); //error, also calls std.math.signbit

Arguably, this is a defect in Phobos.  Looking at the definition of std.math.signbit, it's obvious that it's only meant to handle built-in floating-point types, yet there are no sig constraints to that effect.

Fix: https://github.com/dlang/phobos/pull/6040


T

-- 
The computer is only a tool. Unfortunately, so is the user. -- Armaphine, K5
January 16, 2018
On Tuesday, 16 January 2018 at 20:30:43 UTC, H. S. Teoh wrote:
> On Tue, Jan 16, 2018 at 07:14:00PM +0000, rumbu via
>> 
>> Even specialized, now I have another problem:
>> 
>> std.math:
>> 
>> int signbit(X)(X x) { ... }
>> 
>> mylibrary:
>> 
>> int signbit(D: Decimal!bits, int bits) { ... }
>> 
>> =============
>> 
>> end user:
>> 
>> import std.math;
>> import mylibrary;
>> 
>> Decimal!32 d;
>> float f;
>> 
>> auto y = signbit(f); //ok, call to std.math.signbit
>> auto x = signbit(d); //error, also calls std.math.signbit
>
> Arguably, this is a defect in Phobos.  Looking at the definition of std.math.signbit, it's obvious that it's only meant to handle built-in floating-point types, yet there are no sig constraints to that effect.
>
> Fix: https://github.com/dlang/phobos/pull/6040
>
>
> T

Thank you for the pull request, but the list is longer :)
 https://issues.dlang.org/show_bug.cgi?id=18244